I tried this: List<ClassLoaderFactory.Repository> repositories = new ArrayList<>(); repositories.add(new ClassLoaderFactory.Repository(new File("/dir1").getAbsolutePath(), ClassLoaderFactory.RepositoryType.DIR)); repositories.add(new ClassLoaderFactory.Repository(new File("sub-mod1/target/classes").getAbsolutePath(), ClassLoaderFactory.RepositoryType.DIR)); repositories.add(new ClassLoaderFactory.Repository(new File("sub-mod2/target/classes").getAbsolutePath(), ClassLoaderFactory.RepositoryType.DIR)); File[] files = new File("lib-runtime").listFiles(); for (File file : files) { repositories.add(new ClassLoaderFactory.Repository(file.getAbsolutePath(), ClassLoaderFactory.RepositoryType.JAR)); }
ClassLoader myClassLoader = ClassLoaderFactory.createClassLoader(repositories, null); Thread.currentThread().setContextClassLoader(myClassLoader); SecurityClassLoad.securityClassLoad(myClassLoader); ... Tomcat tomcat = new Tomcat(); tomcat.getService().setParentClassLoader(myClassLoader); And am currently getting this: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]] at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:923) 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.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.base/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.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) So the code looks closer to working, but still something major wrong. On Wed, Dec 21, 2022 at 11:02 AM Tim N <tnti...@gmail.com> wrote: > > The custom class loader approach described in one of the answers is a > > viable option. > > Thanks. > > > No. The same class loader hierarchy isn't constructed when running in > > embedded mode. > > It looks like I would need to replicate all the classloading capabilities > of Tomcat (e.g. loading classes from files and JARs). Any tips for > implementing this? > > It looks like the Tomcat classloader code is available via > https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-catalina. > This isn't a tomcat-embedded module, but looks like it might be compatible. > Could these classes be used to achieve what I'm after? If I could get this > working, I could maybe contribute back with "how-to" documentation. > Thoughts? > > Also, how do I make embedded Tomcat use my classloader? > > > On Wed, Dec 14, 2022 at 9:19 PM Mark Thomas <ma...@apache.org> wrote: > >> On 14/12/2022 03:20, Tim N wrote: >> > I'm currently using embedded Tomcat 9.0.68 and have encountered the >> > infamous compatibility issue with ClassLoader.getSystemClassLoader when >> > upgrading from Java 8 to Java 17. >> > See >> > >> https://stackoverflow.com/questions/46694600/java-9-compatability-issue-with-classloader-getsystemclassloader >> > for a good summary. >> >> The custom class loader approach described in one of the answers is a >> viable option. >> >> > Is it possible to utilise and modify the Tomcat classloader hierarchy >> for >> > embedded Tomcat to add to the classpath, specifically: >> > - Add some shared libraries as done with the 'shared.loader' for >> Tomcat >> > for production and development environments >> >> No. The same class loader hierarchy isn't constructed when running in >> embedded mode. >> >> > - Add another module's classes to the classpath for a web-app for >> > development environment only (e.g. add "../sub-module/target/classes" to >> > classpath) >> >> Yes. Each web application still retains its own class loader. You >> configure the web application resources to map static resources, JARs >> and/or directories of classes to the right place in your web app. >> >> For example (totally untested but should give you the idea): >> >> Tomcat tomcat = new Tomcat(); >> Context context = tomcat.addContext("", "/some/path"); >> WebResourceRoot root = context.getResources(); >> DirResourceSet extraJARs = new DirResourceSet(root, >> "/WEB-INF/lib", "/path/to/extra/jars", ""); >> root.addPostResources(extraJARs); >> >> > In Java 8 I can achieve this by calling 'addURL' on 'URLClassLoader', >> but >> > that is no longer possible in Java 9+. >> > >> > Is there any official documentation for this? >> >> The docs for configuring this in context.xml are here: >> >> https://tomcat.apache.org/tomcat-9.0-doc/config/resources.html >> >> Javadoc for doing it directly is here: >> >> >> https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/webresources/package-summary.html >> >> HTH, >> >> Mark >> > >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org >> For additional commands, e-mail: users-h...@tomcat.apache.org >> >>