-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Possible regression in ContextFactory.getObjectInstance() between Jetty 11.0.22 and 12.0.11 #12094
Comments
I have to ask. Why do you have multiple Server instances in the same JVM? |
@erdi how are you deploying this, is it in the distro or as an embedded application? The exception you describe should really only happen if the webapps are sharing the same classloader, which they should not be. Are you certain that this is the only error, and there's not another exception earlier on in the deployment? A small repro test case would be helpful, as obviously we have checked that deploying multiple webapps to the same |
@erdi you say:
Where/how are you doing "java:comp" lookups before the webapps have been deployed? What do you mean by "application classloader"? Can you please show me an example? In fact, I would really like the smallest repro test case to understand exactly what is happening. |
I'll gladly answer, if you have to ask, @joakime. 🙂 We use multiple |
Thanks for being so responsive, @janbartel.
It's an embedded application, we are using jetty classes in our code.
Their classloaders are sharing a common parent classloader (which is the application/system classloader) and all classes are loaded by that classloader.
I'm fairly certain that this is the exception causing the apps to stop from starting. That's because the apps start up correctly if I wrap the code performing the JNDI lookup using application/system classloader with creating a temporary classloader using application/system classloader as the parent, setting that temporary classloader as the thread context classloader and only then performing the JNDI lookup.
We are using Guice injectors as the backing for web app contexts. As part of instantiation of one of the instances managed by the injector a method from RESTEasy is called which performs a JNDI lookup. This happens before calls to
Using that wording as described here: https://www.baeldung.com/java-classloaders#classloader-types
I will gladly start working on providing you with a project showing the issue now, given you are such an engaged maintainer, @janbartel. Hopefully I will have something ready by the end of the working day and if not then I will update you about the progress. |
That can be entirely handled via the Named connectors and virtualhosts |
Thanks for letting me know, this is definitely a much less clunky solution than using multiple servers for that. I don't believe that using multiple servers is the cause of this issue, though. |
It turns out that creating a reproducer project was much easier than anticipated, @janbartel: https://github.com/erdi/jetty-12094. There is a Please keep in mind that this was quickly put together so it's not cleanest of codes and a lot of it might look artificial. This is just the smallest possible reproducer I could quickly put together for the issue that I'm seeing in my project. |
Oh, if there are any questions about the reproducer then please do let me know, I will happily answer. |
@erdi thanks for that repro, that clarified things. In jetty-12, we have 1 more classloader in the hierarchy as opposed to previous versions of jetty. Before it was the system classloader, the app classloader and then the webapp classloader. Now we have the system classloader, the app classloader, the EE environment classloader, and then the webapp classloader. If I create this environment classloader, your repro starts to work: URLClassLoader environmentLoader = new URLClassLoader(new URL[]{}, Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(environmentLoader);
new InitialContext().lookup("java:comp"); The lines that you saw changed in the |
Thanks Jan. As alluded to in:
I figured out the workaround you mentioned but only applied it at the lookup site rather than globally to reproduce this EE environment classloader because I wasn't aware that it's a thing. I considered applying it now globally but I can see that in #12107 you are already working on reverting the change I mentioned in the description of this issue. I can that the PR is targeted for 12.0.13 and you have a monthly release cadence so it should be available for me at the beginning of September. I'm not pressed for time with this so I will just wait. Thanks again for being so responsive on this. |
This change added an explicit |
@robinvanpraet how long has |
Jetty version(s)
12.0.11
Jetty Environment
ee9
Java version/vendor
(use: java -version)
Issue is not specific to java version used but it's openjdk 21.0.4.
OS type/version
Issue is not specific to OS used but it's macOS Sonoma 14.5
Description
I'm trying to update our apps from Jetty 11.0.22 to 12.0.11. After upgrading, I've noticed that
WebAppContext
s in our apps no longer correctly start up.Each of our apps has multiple
org.eclipse.jetty.server.Server
s, each one of them having aWebAppContext
wrapped in aStatisticsHandler
wrapped in aRewriteHandler
(even thought the fact that they are wrapped doesn't really matter here). The firstWebAppContext
starts ok but the subsequent ones fail with:One notable fact is that as part of application startup some JNDI lookups are performed using the application classloader as the context classloader which is the parent of the web app classloaders used by
WebAppContext
.So what is happening on 12 is:
ContextFactory.__contextMap
EnvConfiguration.createEnvContext()
with a web app class loader as the context classloader is called and the subcontext is added to the context associated with application classloader because it's the parent of the web app classloader and a context was registered for it in the previous stepPlusConfiguration.postConfigure()
comes and callsPlusConfiguration.lockCompEnv()
for the firstWebAppContext
which locks the context associated with the application classloaderEnvConfiguration.createEnvContext()
is called for the secondWebAppContext
and explodes with the above exceptionThis all worked fine on 11 and fails on 12. I tracked it down to this particular change (removal of the lines I'm linking to in the diff): https://github.com/jetty/jetty.project/pull/10897/files#diff-97c1c20fb48f65bd393d8d945d6c1ea54e39527ca7bf5731b2bbe297205e78f7L111-L128. It seems to have been part of the 12.0.5 release. So I believe that the reason why this works on 11 is that on 11 a new context is created for each of the
WebAppContext
's web app classloaders despite there being a context associated with their parent classloader. Interestingly the change in which the removed code was added in 2013 mentions multiple webapps andNamingException
: ecd687d.It still might be the case that this is not a regression but there is something inherently incorrect with our setup. Please advise if that's the case and how to rectify it.
How to reproduce?
Hopefully this is enough information but I can work on providing a self contained reproducible sample project. I would like to have it confirmed that it will be useful, though, before committing to the effort.
The text was updated successfully, but these errors were encountered: