Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class loading issues due to thread context classloader hierarchy (Spring Web Reactive + Tomcat) [SPR-14932] #19499

Closed
spring-issuemaster opened this issue Nov 21, 2016 · 2 comments
Assignees

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Nov 21, 2016

Daniel Fernández opened SPR-14932 and commented

Scenario

This is the scenario:

  • A web application uses a library.
  • That library needs to dynamically load a class that implements a specific interface, for example, in order to select the best implementation for the specific environment in which it is being run.

Observed Result

When using Spring Web Reactive in a Spring Boot 2.0.0 (snapshot) application, if Tomcat is used as a server, a ClassNotFound exception is thrown when the library tries to load the implementation class by means of the thread context class loader.

Example application

Example application: https://github.com/danielfernandez/test-spring-boot-tomcat

The above application replicates the scenario with Spring Boot 1.4.2 and 2.0.0, using Spring Web MVC and Spring Web Reactive (in 2.0.0). Spring Web Reactive is tested both using Netty and Tomcat. Only Tomcat fails.

Possible Diagnosis

This is possibly due to the hierarchy of the thread context class loader. Let's compare:

Thread context class loader in Spring Boot 2.0.0, Spring Web MVC 5.0.0, Tomcat:

+-> sun.misc.Launcher$ExtClassLoader - [sun.misc.Launcher$ExtClassLoader@198ff037]
    +-> sun.misc.Launcher$AppClassLoader - [sun.misc.Launcher$AppClassLoader@330bedb4]
        +-> org.springframework.boot.loader.LaunchedURLClassLoader - [org.springframework.boot.loader.LaunchedURLClassLoader@65ab7765]
            +-> org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader - [TomcatEmbeddedWebappClassLoader\n\n  context: ROOT\n\n  delegate: true\n\n----------> Parent Classloader:\n\norg.springframework.boot.loader.LaunchedURLClassLoader@65ab7765\n\n]

Thread context class loader in Spring Boot 2.0.0, Spring Web Reactive 5.0.0, Netty:

+-> sun.misc.Launcher$ExtClassLoader - [sun.misc.Launcher$ExtClassLoader@67449f2]
    +-> sun.misc.Launcher$AppClassLoader - [sun.misc.Launcher$AppClassLoader@330bedb4]
        +-> org.springframework.boot.loader.LaunchedURLClassLoader - [org.springframework.boot.loader.LaunchedURLClassLoader@65ab7765]

Thread context class loader in Spring Boot 2.0.0, Spring Web Reactive 5.0.0, Tomcat:

+-> sun.misc.Launcher$ExtClassLoader - [sun.misc.Launcher$ExtClassLoader@32e33c96]
    +-> sun.misc.Launcher$AppClassLoader - [sun.misc.Launcher$AppClassLoader@330bedb4]
        +-> org.apache.catalina.loader.ParallelWebappClassLoader - [ParallelWebappClassLoader\n\n  context: ROOT\n\n  delegate: false\n\n----------> Parent Classloader:\n\nsun.misc.Launcher$AppClassLoader@330bedb4\n\n]

Given the org.springframework.boot.loader.LaunchedURLClassLoader is the one which class path contains all the .jar files contained inside the Spring Boot über jar, it seems as if the org.apache.catalina.loader.ParallelWebappClassLoader used as a thread context class loader in Spring Web Reactive + Tomcat should be delegating to LaunchedURLClassLoader. But it isn't.

Please see the README for the example application on GitHub for more detail on how this was tested and diagnosed.

Impact

This affects the integration of Thymeleaf into applications using Spring Web Reactive. Thymeleaf needs to initialise some implementations depending on the specific scenario it is being run on, and this issue makes it impossible to use the current version of the Thymeleaf + Spring integration packages in Spring Web Reactive applications using Tomcat.


Affects: 5.0 M3

Reference URL: https://github.com/danielfernandez/test-spring-boot-tomcat

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jan 4, 2017

Brian Clozel commented

Thanks a lot Daniel Fernández for this super thorough bug report and repro applications.
This is something I totally overlooked when I created the minimal setup for a Tomcat container.

I've just fixed this issue by using the TomcatEmbeddedWebappClassLoader Boot infrastructure. I'm in the process of moving that starter to Boot proper, since we've reached a point where we need more and more advanced features and to reuse Boot's infrastructure.

I'm resolving this as invalid since this issue is about the experimental Spring Boot reactive web starter and I don't want to mislead people since no commit in Framework fixed this.

Thanks again!

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jan 4, 2017

Daniel Fernández commented

Awesome. Thank you for fixing it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.