Tomcat Embedded Project работает в Eclipse, но не работает как выполнимый Jar - PullRequest
0 голосов
/ 17 февраля 2019

Цель - это веб-приложение в автономном исполняемом фляге, включающем в себя Tomcat Embedded.
Оно прекрасно работает и без проблем работает в Eclipse.Затем после экспорта проекта в виде файла 'Runnable Jar' и попытки запустить его из консоли cmd с помощью java -jar filename.jar происходит сбой со многими ошибками.

Это всего один файл.Вот код:

package test.example.tomcat;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;


public class Main {

    public static void main(String[] args) {

        // URL in browser would be:
        // localhost:8080/tce/
         try {
            new Main().start();
        } catch (MalformedURLException | ServletException | LifecycleException e) {
            System.out.println("Error: Setting up Tomcat failed.\n"+e.getMessage());
            e.printStackTrace();
        }
    }
    public void start() throws ServletException, LifecycleException, MalformedURLException {

    Tomcat tomcat = new Tomcat();
    // set port
    String webPort = System.getenv("PORT");
    if(webPort == null || webPort.isEmpty()) {
        webPort = "8080";
    }
    tomcat.setPort(Integer.valueOf(webPort));

    // detrmine webapp local path
    String webappDirLocation = "WebContent/";
    // detrmine context path
    String contextPath = "/tce";
    // detrmine base directory for files
    String docBase = new File(webappDirLocation).getAbsolutePath();
    // detrmine servlet name
    String servletName = "TcEEx";
    // detrmine root url path
    String urlPattern = "/";

    // create a very basic servlet
    HttpServlet servlet = new HttpServlet() {

        private static final long serialVersionUID = 1L;

        @Override
        public void init(ServletConfig config) throws ServletException {
            System.out.println("Gooooooooooooooooood Morning!");                
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            PrintWriter writer = resp.getWriter();

            writer.println("<html><title>Welcome</title><body>");
            writer.println("<h1>Have a Great Day!</h1>");
            writer.println("</body></html>");
        }
    };

    // set server base directory
    tomcat.setBaseDir(System.getProperty("java.io.tmpdir"));
    // instantiate context
    Context ctx = tomcat.addContext(contextPath, docBase);
    // add regular servlet
    tomcat.addServlet(contextPath, servletName, servlet);
    // map servlet
    ctx.addServletMappingDecoded(urlPattern, servletName);
    // get the default HTTP connector
    tomcat.getConnector();

    // start server
    try {
        tomcat.start();
    } catch (LifecycleException e) {
        System.out.println("Error: Starting Tomcat failed."+e.getMessage());
        e.printStackTrace();
      }
    tomcat.getServer().await();
    }

}

консольный вывод:

Feb 17, 2019 10:53:20 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
Feb 17, 2019 10:53:20 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Tomcat]
Feb 17, 2019 10:53:20 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet engine: [Apache Tomcat/9.0.16]
Feb 17, 2019 10:53:20 AM org.apache.catalina.core.ContainerBase startInternal
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@4fb64261]
        at java.util.concurrent.FutureTask.report(Unknown Source)
        at java.util.concurrent.FutureTask.get(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:928)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Tomcat.start(Tomcat.java:455)
        at test.example.tomcat.Main.start(Main.java:98)
        at test.example.tomcat.Main.main(Main.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@4fb64261]
        at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:139)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:173)
        at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4783)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4918)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
        ... 22 more
Caused by: java.lang.Error: factory already defined
        at java.net.URL.setURLStreamHandlerFactory(Unknown Source)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.<init>(TomcatURLStreamHandlerFactory.java:130)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstanceInternal(TomcatURLStreamHandlerFactory.java:53)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.register(TomcatURLStreamHandlerFactory.java:77)
        at org.apache.catalina.webresources.StandardRoot.registerURLStreamHandlerFactory(StandardRoot.java:699)
        at org.apache.catalina.webresources.StandardRoot.initInternal(StandardRoot.java:682)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        ... 32 more

Feb 17, 2019 10:53:20 AM org.apache.catalina.core.ContainerBase startInternal
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: A child container failed during start
        at java.util.concurrent.FutureTask.report(Unknown Source)
        at java.util.concurrent.FutureTask.get(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:928)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Tomcat.start(Tomcat.java:455)
        at test.example.tomcat.Main.start(Main.java:98)
        at test.example.tomcat.Main.main(Main.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:921)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
        ... 14 more
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@4fb64261]
        at java.util.concurrent.FutureTask.report(Unknown Source)
        at java.util.concurrent.FutureTask.get(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        ... 22 more
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@4fb64261]
        at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:139)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:173)
        at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4783)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4918)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
        ... 22 more
Caused by: java.lang.Error: factory already defined
        at java.net.URL.setURLStreamHandlerFactory(Unknown Source)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.<init>(TomcatURLStreamHandlerFactory.java:130)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstanceInternal(TomcatURLStreamHandlerFactory.java:53)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.register(TomcatURLStreamHandlerFactory.java:77)
        at org.apache.catalina.webresources.StandardRoot.registerURLStreamHandlerFactory(StandardRoot.java:699)
        at org.apache.catalina.webresources.StandardRoot.initInternal(StandardRoot.java:682)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        ... 32 more

Error: Starting Tomcat failed.A child container failed during start
org.apache.catalina.LifecycleException: A child container failed during start
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:921)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:928)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Tomcat.start(Tomcat.java:455)
        at test.example.tomcat.Main.start(Main.java:98)
        at test.example.tomcat.Main.main(Main.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: A child container failed during start
        at java.util.concurrent.FutureTask.report(Unknown Source)
        at java.util.concurrent.FutureTask.get(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        ... 14 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:921)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
        ... 14 more
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@4fb64261]
        at java.util.concurrent.FutureTask.report(Unknown Source)
        at java.util.concurrent.FutureTask.get(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        ... 22 more
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@4fb64261]
        at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:139)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:173)
        at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4783)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4918)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
        ... 22 more
Caused by: java.lang.Error: factory already defined
        at java.net.URL.setURLStreamHandlerFactory(Unknown Source)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.<init>(TomcatURLStreamHandlerFactory.java:130)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstanceInternal(TomcatURLStreamHandlerFactory.java:53)
        at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.register(TomcatURLStreamHandlerFactory.java:77)
        at org.apache.catalina.webresources.StandardRoot.registerURLStreamHandlerFactory(StandardRoot.java:699)
        at org.apache.catalina.webresources.StandardRoot.initInternal(StandardRoot.java:682)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        ... 32 more

релевантный подробности:

  • Apache Tomcat 9.0.16 Embedded
  • Банки Tomcat находятся в Classpath (путь сборки Java)
  • Eclipse Oxygen.3a 4.7.3a
  • Webapp, созданный какдинамический веб-проект
  • без использования maven / gradle и т. д. и без фреймворка, такого как Spring.Делаем это вручную.
  • Java 1.8.201
  • Win7 / x64

После исследования похожих вопросов на stackoverflow / google и их предложениях / ответах, вот некоторыеиз попыток согласования, которые не смогли (или исключены) для решения этой проблемы:

  • Очистить / восстановить проект перед экспортом ..
  • Проверенные файлы Tomcat были включеныв моем банке.
  • Убедитесь, что порт свободен.
  • Повторная загрузка Jars
  • Попытка каждого из трех вариантов обработки библиотеки в диалоге исполняемого файла Jar Eclipse
  • Воссоздание проекта как Java-проекта вместо динамического веб-приложения (это фактически сделало проект не запущенным в Eclipse).

1 Ответ

0 голосов
/ 18 февраля 2019

Хорошо, решил это самостоятельно, поэтому я оставлю этот вопрос в курсе и сам отвечу на него, потому что это довольно минималистичный и хороший пример кода для работающего Webapp с последним, на данный момент, встроенным Tomcat, который можно легко упаковать.в автономную и исполняемую флягу и все это без каких-либо сторонних инструментов для упаковки фляг / банок или инструментов для автоматизации упаковки.Я ХОЧУ, чтобы кто-то оставил этот пост с этим решением для меня.Это сэкономило бы столько времени и усилий.

Итак, вот что не так:
первый шаг
Как видно из вывода консоли в исходном вопросе, есть некоторыестолкновения между классами и методами.Это произошло потому, что при экспорте проекта Eclipse в исполняемый файл JAR был выбран неправильный параметр.
Существует 3 варианта:

  • Извлечение необходимых библиотек в сгенерированный JAR
  • Упакуйте необходимые библиотеки в сгенерированный JAR
  • Скопируйте необходимые библиотеки в подпапку рядом с сгенерированным JAR

Второй был выбран, но затем произошли эти конфликты.При выборе первого варианта таких столкновений не бывает.

шаг второй
Но затем он все равно не запускается из-за отсутствия каталога WebContent, который, как ожидается, будет находиться в том же пути, что и jar.Таким образом, быстрое решение, просто чтобы доказать, что он работает с каталогом там (конечно, не для производства), состоит в том, чтобы создать его при первом запуске программы с
new File ("./ WebContent"). Mkdirs ();
например, в методе main или в любом месте до его использования.

edit
Единственное предостережение, поскольку этот параметр извлекает фляги зависимостей и перепаковывает их с оригинальной зависимостьюФляги одного и того же вендора + проекта, имеют один и тот же домен и будут смешиваться, что также может привести к конфликтам имен файлов в будущем при добавлении нескольких фляг.Так что я все еще открыт для кого-то с лучшим ответом , который не требует слишком большой зависимости от сторонних инструментов.Было бы хорошо, если бы основной jar мог хранить другие зависимости как jar вместо извлеченных.Также был бы полезен другой способ, который не позволял бы смешивать файлы зависимостей, несмотря на случаи с одинаковыми путями.

...