Cannot add web application to built-in Tomcat of @SpringBootApplication with main-thread's context class loader

自作多情 提交于 2020-01-07 02:29:27

问题


I am trying to load a war as web application that I ship with my standalone jar. As my @SpringBootApplication is starting up, I extract the war file and copy it to the file system. After that I make a simple tomcat.addWebapp() call which I'd expect to work. But take a look:

@Bean
public EmbeddedServletContainerFactory servletContainerFactory() {

    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {

            String appHome = System.getProperty(Environment.APP_HOME);

            String targetFileName = "web-0.0.1-SNAPSHOT.war";               
            InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(targetFileName);

            File target = new File(Paths.get(appHome, targetFileName).toString());

            try {

                // Copy the file to the file system
                java.nio.file.Files.copy(resourceAsStream, target.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING);

                // Add the web application and bind it to the context path /web
                Context context = tomcat.addWebapp("/web", target.getAbsolutePath());
                WebappLoader loader = new WebappLoader(Thread.currentThread().getContextClassLoader());
                context.setLoader(loader);

            } catch (ServletException ex) {
                throw new IllegalStateException("Failed to add webapp", ex);
            } catch(Exception e) {                  
                throw new IllegalStateException("Failed to add webapp", e);
            }
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }
    };
}

The problem is that I am getting tons of FileNotFoundException right after the servletContainerFactory() returns. You can see the full output here but it boils down to:

java.io.IOException: Unable to create the directory [/tmp/tomcat.2878705033245220680.8080/webapps/web]
    at org.apache.catalina.startup.ExpandWar.expand(ExpandWar.java:115) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.startup.ContextConfig.fixDocBase(ContextConfig.java:615) [tomcat-embed-core-8.5.11.jar:8.5.11]
..
2017-02-12 19:39:44.393  INFO 10137 --- [ost-startStop-1] o.apache.catalina.startup.ContextConfig  : No global web.xml found
2017-02-12 19:39:44.590  WARN 10137 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner  : Failed to scan [file:/home/stefan/.m2/repository/org/bytedeco/javacv/1.3/javacpp-1.3.jar] from classloader hierarchy
..
java.io.FileNotFoundException: /home/stefan/.m2/repository/org/bytedeco/javacv/1.3/javacpp-1.3.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
..
2017-02-12 19:39:44.590  WARN 10137 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner  : Failed to scan [file:/home/stefan/.m2/repository/org/bytedeco/javacv/1.3/opencv-3.1.0-1.3.jar] from classloader hierarchy
..
java.io.FileNotFoundException: /home/stefan/.m2/repository/org/bytedeco/javacv/1.3/opencv-3.1.0-1.3.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
..
2017-02-12 19:39:44.591  WARN 10137 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner  : Failed to scan [file:/home/stefan/.m2/repository/org/bytedeco/javacv/1.3/ffmpeg-3.2.1-1.3.jar] from classloader hierarchy
..
java.io.FileNotFoundException: /home/stefan/.m2/repository/org/bytedeco/javacv/1.3/ffmpeg-3.2.1-1.3.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
..

The last exception is a ClassNotFoundException which surely is connected to the errors above:

java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:520) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:501) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:118) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1050) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:989) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4913) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5223) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

It seems that all dependencies are simply missing. The question is what I have to do in order to fix this. As suggested I have also put the tomcat-embed-core dependency to the pom.xml of the Spring application but this did not work.

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>8.5.11</version>
</dependency>

Any help is appreciated!


回答1:


For java.io.FileNotFoundException, the solution can be found in https://stackoverflow.com/a/37857690

The ClassNotFoundException can be fixed by adding:

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <version>8.5.11</version>
</dependency>


来源:https://stackoverflow.com/questions/42191815/cannot-add-web-application-to-built-in-tomcat-of-springbootapplication-with-mai

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!