When a web app is started on standalone Tomcat the WebappClassLoader is created and used to load all of the application's types. It's also the thread context class loader when the application's started. In a Boot app the uses embedded Tomcat things are a little different. The application's types are loaded on the main thread using Boot's class loader. Tomcat's then started and the WebappClassLoader is created. This class loader then isn't set as the context class loader when the application's started.
One problem that this causes is that it breaks JNDI lookups performed during startup. If you use postProcessContext to configure JNDI, this is done on one of Tomcat's startup threads. If you then attempt a JNDI lookup during application startup this lookup happens on the main thread. The lookup fails as there's nothing linking the main thread to the JNDI context. Setting the main thread's context class loader to be Tomcat's WebappClassLoader fixes this.
Comment From: derkoe
Here's the corresponding stackoverflow question: http://stackoverflow.com/questions/27822619/howto-use-jndi-database-connection-with-spring-boot-and-spring-data-using-embedd
and the sample application setting the context class loader in the TomcatEmbeddedServletContainerFactory: https://github.com/derkoe/spring-boot-sample-tomcat-jndi
Comment From: josetesan
Yes, definitely yes ! I do believe spring-boot was the 'apple' of the java environment .. the 'we take care of all the background, you just do the business logic' paradigma, and imho, this one could be done from inside boot tomcat capabilities.
Comment From: bharath0091
I am getting the same error reported here again in spring-boot 1.4.1.RELEASE version.
Comment From: philwebb
@bharath0091 This issue has been closed since 2015. If you've found a similar issue please could you open a new report and provide a sample application that shows the problem. You should also consider upgrading to 1.5 if possible.
Comment From: PerfecterDay
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
TomcatEmbeddedServletContainer container = super.getTomcatEmbeddedServletContainer(tomcat);
Container context = container.getTomcat().getHost().findChild("");
ClassUtils.overrideThreadContextClassLoader(context.getLoader().getClassLoader());
return container;
}
how to get this -> context.getLoader().getClassLoader(); with the tomcat-core 8.5 ?
Comment From: AlexSylka
We also have classloader issue but I am not sure if it's related to spring-boot or orika https://stackoverflow.com/q/52321672/4507790
Comment From: AlexSylka
@Override protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer( Tomcat tomcat) { tomcat.enableNaming(); TomcatEmbeddedServletContainer container = super.getTomcatEmbeddedServletContainer(tomcat); Container context = container.getTomcat().getHost().findChild(""); ClassUtils.overrideThreadContextClassLoader(context.getLoader().getClassLoader()); return container; }how to get this -> context.getLoader().getClassLoader(); with the tomcat-core 8.5 ?
@PerfecterDay @wilkinsona There is no such class in spring bot 2.0.3 TomcatEmbeddedServletContainer. Do you know how to apply this fix in spring boot 2.0.3 ?
Comment From: wilkinsona
@AlexSylka Please don't make the same comment on multiple issues. It creates unnecessary noise for anyone watching the repository.
TomcatEmbeddedServletContainer is TomcatServletWebServerFactory in Spring Boot 2.0. If you have any further questions, please stick to Stack Overflow or chat with the community on Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.
Comment From: FellinRoberto
Hello! I'm sorry to bother you about something so old, but I am still experiencing this issue with Spring Boot 2.6.13. Using the following work around solves the problem:
for (Container child : container.getTomcat().getHost().findChildren()) {
if (child instanceof Context) {
ClassLoader contextClassLoader = ((Context) child).getLoader().getClassLoader();
Thread.currentThread().setContextClassLoader(contextClassLoader);
break;
}
}
From what is written in this thread, the problem should have been fixed in version 1.4.0. Could you tell me if there is a version that solves it directly?
Thanks for your time.
Comment From: wilkinsona
@FellinRoberto Without knowing exactly what your problem is it's very hard for us to identify a "version that solves it directly". At this time, we're not aware of any problem with Tomcat and the thread context class loader. If you've found a problem that you would like us to investigate, please open a new issue and provide a minimal sample that reproduces the problem.
Comment From: FellinRoberto
Thanks for your quick reply. I opened #35584