I have an issue with embedded Tomcat and classloaders.
I have a java servlet application that runs in an embedded Tomcat(9.0.70) instance. When the application is packaged into a single war file – the application loads and performs as expected (classes are fond in WEB-INF/lib.
Due to some system constraints it is necessary to deliver the application code separate from its dependencies.
I modified the application pom to copy the dependencies to ${project.build.directory}/lib/
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<id>copy-dependencies</id>
<goal>copy-dependencies</goal>
<configuration> <outputDirectory>${project.build.directory}/lib/</outputDirectory>
<code><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration> <outputDirectory>${project.build.directory}/lib/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</code>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration> <outputDirectory>${project.build.directory}/lib/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
and to exclude the jar files from the war file
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
<code> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
</configuration>
</plugin>
</code>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
</configuration>
</plugin>
this builds the project as expected – 1 war file and one lib directory.
The class that creates the embedded Tomcat environment includes (much abbreviated):
<code>System.setProperty("catalina.home", catHome) ;
server = tomcat.getServer();
File base = server.getCatalinaBase();
File home = server.getCatalinaHome();
log.info("starting on port:" + sslPort +
" with home:" + home.getAbsolutePath() +
" base:" + base.getAbsolutePath());
<code>System.setProperty("catalina.home", catHome) ;
tomcat.start();
server = tomcat.getServer();
File base = server.getCatalinaBase();
File home = server.getCatalinaHome();
log.info("starting on port:" + sslPort +
" with home:" + home.getAbsolutePath() +
" base:" + base.getAbsolutePath());
</code>
System.setProperty("catalina.home", catHome) ;
tomcat.start();
server = tomcat.getServer();
File base = server.getCatalinaBase();
File home = server.getCatalinaHome();
log.info("starting on port:" + sslPort +
" with home:" + home.getAbsolutePath() +
" base:" + base.getAbsolutePath());
The logging confirms that CATALINA_HOME is se to the required dir.
On execution receive ClassNotFoundException
<code>java.lang.ClassNotFoundException: com.google.gwt.user.server.rpc.RemoteServiceServlet
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1412)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220)
at java.lang.ClassLoader.defineClassImpl(Native Method)
at java.lang.ClassLoader.defineClassInternal(ClassLoader.java:396)
at java.lang.ClassLoader.defineClass(ClassLoader.java:357)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:154)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2472)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:875)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1376)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:534)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:515)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:149)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1067)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1007)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4948)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
at java.util.concurrent.FutureTask.run(FutureTask.java:277)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
at java.util.concurrent.FutureTask.run(FutureTask.java:277)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:430)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486)
<code>java.lang.ClassNotFoundException: com.google.gwt.user.server.rpc.RemoteServiceServlet
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1412)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220)
at java.lang.ClassLoader.defineClassImpl(Native Method)
at java.lang.ClassLoader.defineClassInternal(ClassLoader.java:396)
at java.lang.ClassLoader.defineClass(ClassLoader.java:357)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:154)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2472)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:875)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1376)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:534)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:515)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:149)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1067)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1007)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4948)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
at java.util.concurrent.FutureTask.run(FutureTask.java:277)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
at java.util.concurrent.FutureTask.run(FutureTask.java:277)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:430)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486)
</code>
java.lang.ClassNotFoundException: com.google.gwt.user.server.rpc.RemoteServiceServlet
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1412)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220)
at java.lang.ClassLoader.defineClassImpl(Native Method)
at java.lang.ClassLoader.defineClassInternal(ClassLoader.java:396)
at java.lang.ClassLoader.defineClass(ClassLoader.java:357)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:154)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2472)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:875)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1376)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:534)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:515)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:149)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1067)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1007)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4948)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
at java.util.concurrent.FutureTask.run(FutureTask.java:277)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
at java.util.concurrent.FutureTask.run(FutureTask.java:277)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:430)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486)
my understanding from https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html is that the Tomcat common loader will search for jars in CATALINA_HOME/lib. My $CATALINA_HOME/lib contains gwt-user-2.10.0.jar which contains RemoteServiceServlet.class.
What do I need to do to resolve from CATALINA_HOME/lib
do i need my own classloader – from the Tomcat doc the common loader should be sufficient (I think)