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

ServiceLoader loads default providers ahead of application providers #350

Closed
timguy opened this issue Nov 1, 2018 · 7 comments
Closed

Comments

@timguy
Copy link

timguy commented Nov 1, 2018

What
I just upgraded from 1.5.6 to 1.6.2 and saw that my META-INF/javamail.default.providers is not used anymore.

Why
I watched into the code and saw the difference.

  • In 1.5.6 during Session creation the providers were loaded in the constructor (call loadProviders(cl) in line 225 ).
  • Now with 1.6.2 the constructor in Session does nothing about the providers.

According to current 1.6.2 javadoc documentation use of javamail.default.providers file should continue to work.
Also here https://javaee.github.io/javamail/docs/CHANGES.txt I could not found any documented breaking changes.

Consequence
So my current issue is that I am depending on third library (JavaMailSenderImpl spring-context-support-5 via spring-boot-starter-mail:2.0.6) and their usage is like:

Session.getInstance(this.javaMailProperties)
session.getTransport(protocol)

and described behaviour has changed.

Workaround

  • On a quick view seems I need to call
    session.getProviders() between Session.getInstance( and session.getTransport now?
  • Or maybe I should use the "configuring providers using java.util.ServiceLoader" if this is possible without code change/ overriding on spring side
@bshannon
Copy link
Contributor

bshannon commented Nov 1, 2018

The javamail.default.providers file is now loaded on demand.
If the requested provider is found using the ServiceLoader mechanism,
the javamail.default.providers file may never be loaded.

What protocol provider are you trying to use? Is it not being found?
What does the JavaMail debug output show?

@timguy
Copy link
Author

timguy commented Nov 2, 2018

The javamail.default.providers file is now loaded on demand.

Ok that's issue for me and what I have seen in the Session constructor change.
Providers are not loaded anymore from the file in the classpath at this place.

What protocol provider are you trying to use? Is it not being found?

Don't know if I got you right, but I was loading the providers via this example

What does the JavaMail debug output show?

Just version number but no issues. With old version it shows the file is loaded but with new version of course it isn't shown

Thanks

@bshannon
Copy link
Contributor

bshannon commented Nov 2, 2018

Are you trying to replace the real protocol providers with mock protocol providers, for testing?
You'll need to either use a different protocol name for the mock providers, or use the JavaMail
jar file that doesn't contain any of the default providers. Possibly you can configure your mock
providers using the ServiceLoader mechanism and make sure they're in the classpath before
the JavaMail jar file.

@timguy
Copy link
Author

timguy commented Nov 4, 2018

Are you trying to replace the real protocol providers with mock protocol providers, for testing?

Yes, I replaced Transport and IMAPStore with Mock classes which extends the Transport and IMAPStore. And well, I was not trying but acutally doing this with version 1.5.6.
Currently I force my gradle to stay with the old version because I can't change spring-boot-starter-mail how they use javamail.

So there is no chance that loading providers (...and looking for META-INF/javamail.default.providers) is coming back into the Session.getInstance constructor with a later release?

@bshannon
Copy link
Contributor

bshannon commented Nov 4, 2018

No, the addition of support for loading providers using the ServiceLoader mechanism
is necessary for support of the new Java module system.

A few points...

It was never intended that you would replace the javamail.default.providers file. That
file was intended as the built in defaults. If you wanted to supply your own providers,
they should be configured in a javamail.providers file.

There was never a well defined mechanism for overriding the included providers.
Possibly you could control this by placement on the classpath, did you try that?
But really the expectation was that if you didn't want the included providers you
would use the mailapi.jar file that didn't include those providers.

The existing providers were not designed to be extended by users of JavaMail, but
if you wanted to do that you should use a different protocol name for the extended
version. JavaMail does this itself with the "gimap" provider.

Have you tried including a META-INF/services/javax.mail.Provider file in your mock
provider, and putting your mock provider on the classpath before the JavaMail jar file?

@timguy
Copy link
Author

timguy commented Nov 5, 2018

It was never intended that you would replace the javamail.default.providers file.
Ok good to know that. So I have to switch away from this mock solution

Currently I use the 1.5.6 and we run with that. But for sure there will be soltuion got get it mocked. You named already some and I am sure it will work :-). Thanks so far.

Update
I adapted not to use META-INF/javamail.default.provide anymore. Now I directly create and set Providers (session.setProvider) with mock classes for Transport and Store. (And provide the session as bean in spring project and set the JavaMailSender.setSession)

@timguy timguy closed this as completed Nov 15, 2018
@bshannon bshannon reopened this Mar 22, 2019
@bshannon
Copy link
Contributor

Some other people have run into this issue as well and it's now clear that
the change to use ServiceLoader is not sufficiently compatible with some
common uses.

To be clear, an application should never include a javamail.default.providers file.
But it should be able to include a javamail.providers file that overrides what's in
JavaMail's javamail.default.providers file.

@bshannon bshannon changed the title Session - Loading of providers - difference between versions ServiceLoader loads default providers ahead of application providers Mar 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants