-
Notifications
You must be signed in to change notification settings - Fork 100
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
Jakarta Mail erroneously assumes that classes can be loaded from Thread#getContextClassLoader
#665
Comments
For Jakarta Mail, such a change could have unwanted side effects since the users should continue being able to load custom providers, which in general are only visible to the application classloader: https://jakarta.ee/specifications/mail/2.1/jakarta-mail-spec-2.1.html#resource-files |
The application classloader generally has access to custom providers and Jakarta Mail. The risk is nonzero but should be acceptable given the benefits. The current status quo is completely infeasible for modular applications like Jenkins. |
I would think that we could use a fallback strategy sort of like what is done in Session::getService but instead of applying it to services we apply it to providers. |
@jmehrens Would you accept a PR for this? If so, could you please go into a lot more detail about how you would want it to be implemented? |
I would accept a PR for this. As the problem and the solution should be the similar to #144.
I haven't tested or even compiled this is just a general idea on how session should traverse the classloader maze as it is the same logic that is used when creating Transport or a Store from the Session. My understanding is that this approach would satisfy compatibility concerns around this PR as it is building on an older precedent already established in the project. |
Hi all - is there a fix for this? I am having the same issue with spring-boot-starter-mail 3.1.1, java 17 I found this issue from here https://groups.google.com/g/wildfly/c/dwVsQoui6Us which is the same issue I am having but not in wildfly |
Sorry to comment again but this is a blocker for me - I have asked on stackoverflow but doesn't seem to have an answer Any help much appreciated... |
I answered the SO question. For now you have to use the same workaround as described above in this ticket which is to set/reset the context classloader before use. |
We have hundreds of such call sites, making it prohibitively difficult to work around the problem in this way throughout the Jenkins ecosystem. Please fix this bug. |
Happy New Year! A friendly ping that we are still impacted by this bug and are looking forward to the release of a fix. |
Problem
When attempting to use Jakarta Mail API 2.1.1 within a Jenkins plugin, the following error occurs:
Evaluation
The cause is explained in this page. The caller
hudson.tasks.Mailer
is a Jenkins plugin whose class loader is notThread#getContextClassLoader
but which can see the classes in the Jenkins Mailer plugin and its dependencies (including the Jenkins Jakarta Mail plugin).Thread#getContextClassLoader
is set to the Jenkins core class loader, which cannot see any Jenkins plugins. Since we bundle Jakarta Activation and Jakarta Mail as Jenkins plugins, invokingmail-api/api/src/main/java/jakarta/mail/util/FactoryFinder.java
Line 118 in e8622ce
ServiceLoader#load(Class service, ClassLoader loader)
, usesThread#getContextClassLoader
) from a Jenkins plugin attempts to find the class in the Jenkins core class loader (which cannot see classes in Jenkins plugins) and fails.At its core, the problem is that Jakarta Mail generally (and
StreamProvider
in particular) assumes thatThread#getContextClassLoader
has access to the classes that the calling class has access to. This assumption is usually true, but it is not true for Jenkins and other modular applications with a plugin system implemented with a class loader hierarchy.Workaround
We can successfully work around the problem with code like
at each call site in each Jenkins plugin, but there are hundreds of such call sites, making it prohibitively difficult to work around the problem in this way throughout the Jenkins ecosystem.
Suggested solution
Please modify the default behavior to load classes with
getClass().getClassLoader()
instead ofThread#getContextClassLoader
by changingmail-api/api/src/main/java/jakarta/mail/util/FactoryFinder.java
Line 118 in e8622ce
ServiceLoader.load(factory, getClass().getClassLoader())
. Such a change might seem risky, but it was successfully done (at the request of the Jenkins core developers) after a Twitter discussion in Jackson in FasterXML/jackson-dataformat-xml@97fe9eb without causing regressions for end users.Note
Note that a similar problem exists in Jakarta Activation in https://github.com/jakartaee/jaf-api/blob/b7fb44ae9d1872bf86b4098f8f1462e7f7b05a3c/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java#L31, but prior to #579 I was able to work around the problem with gross hacks like https://github.com/jenkinsci/jakarta-mail-api-plugin/tree/32b196156bd5774402bd1d5ec6de8ff3665e4b9c/src/main/java/io/jenkins/plugins/jakarta/activation. As of #579 the same problem is also present in Jakarta Mail, and I see no workaround. The ask is for both Jakarta Mail and Jakarta Activation to load classes with
getClass().getClassLoader()
instead ofThread#getContextClassLoader
.The text was updated successfully, but these errors were encountered: