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

java.lang.IllegalStateException: Not provider of jakarta.mail.util.StreamProvider was found #85

Closed
viragpurnam opened this issue Feb 9, 2023 · 16 comments

Comments

@viragpurnam
Copy link

Describe the bug
I am updating my project dependencies from com.sun.mail:jakarta.mail (2.0.1) to jakarta.mail-api and angus-mail.
But after doing changes in pom.xml. I get the below error.

java.lang.IllegalStateException: Not provider of jakarta.mail.util.StreamProvider was found
	at jakarta.mail.util.FactoryFinder.find(FactoryFinder.java:64)
	at jakarta.mail.util.StreamProvider.provider(StreamProvider.java:186)
	at jakarta.mail.Session.<init>(Session.java:254)
	at jakarta.mail.Session.getDefaultInstance(Session.java:381)
@jbescos
Copy link
Member

jbescos commented Feb 10, 2023

Could you run the next and copy-paste the output?:

mvn dependency:tree

@viragpurnam
Copy link
Author

viragpurnam commented Feb 10, 2023

Hi @jbescos: Some how dependency tree is not working for this module alone.
I have attached a code snippet, which is responsible. It works good when I use com.sun.mail:jakarta.mail or org.eclipse.angus:jakarta.mail.

public void sendEMail(String subject, String content) throws MessagingException {
		Properties props = new Properties();
		props.put("mail.smtp.starttls.enable", getSmtpSTARTTLS());
		Session session = Session.getInstance(props, null);
		UserPassword credentials = getSmtpCredentials();
		URLName urlName = createURLName(credentials);
		session.setPasswordAuthentication(urlName,
				new PasswordAuthentication(credentials.getUser(), credentials.getPassword()));
		if (Environment.isDebug()) {
			session.setDebug(true);
		}

		Message msg = new MimeMessage(session);
		if (getFrom() != null && getFrom().length() > 0) {
			msg.setFrom(new InternetAddress(getFrom()));
		}
		if (getTo() != null && getTo().length() > 0) {
			msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(getTo(), false));
		}
		if (getCc() != null && getCc().length() > 0) {
			msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(getCc(), false));
		}
		msg.setSubject(subject);
		msg.setText(content);
		msg.setHeader("X-Mailer", MAILER); //$NON-NLS-1$
		msg.setSentDate(new Date());

		// send the thing off
		Transport transport = session.getTransport(urlName);
		transport.connect();
		transport.sendMessage(msg, msg.getAllRecipients());
		transport.close();
	}

@viragpurnam
Copy link
Author

viragpurnam commented Feb 10, 2023

In Session.java there is call for StreamProvider, and that is creating an issue in my case.

// Constructor is not public
  private Session(Properties props, Authenticator authenticator) {
  	this.props = props;
  	this.authenticator = authenticator;
  	this.streamProvider = StreamProvider.provider();
  
  	if (Boolean.valueOf(props.getProperty("mail.debug")).booleanValue())
  	    debug = true;
  
  	initLogger();
  	logger.log(Level.CONFIG, "Jakarta Mail version {0}", Version.version);
  
  	// get the Class associated with the Authenticator
  	Class<?> cl;
  	if (authenticator != null)
  	    cl = authenticator.getClass();
  	else
  	    cl = this.getClass();
  	// load the resources
  	loadProviders(cl);
  	loadAddressMap(cl);
  	q = new EventQueue((Executor)props.get("mail.event.executor"));
  }

@jbescos
Copy link
Member

jbescos commented Feb 10, 2023

That error means that it cannot find the implementation of jakarta.mail.util.StreamProvider, that is supposed to exist in angus-mail.

It seems to me that angus-mail dependency is not available in runtime. We would need to get the classpath/modulepath of your java process.

Try to remove any mail/angus-mail dependency you have in the pom, and just add this one (it will bring any required dependency transitively):

		<dependency>
			<groupId>org.eclipse.angus</groupId>
			<artifactId>angus-mail</artifactId>
			<version>2.0.1</version>
		</dependency>

If this does not work, then remove it and add this other (that contains mail and angus-mail within the same jar):

		<dependency>
			<groupId>org.eclipse.angus</groupId>
			<artifactId>jakarta.mail</artifactId>
			<version>2.0.1</version>
		</dependency>

If none of previous solutions work, are you able to provide the classpath/modulepath of the java process?.

@viragpurnam
Copy link
Author

Hi @jbescos,
Adding jakarta.mail works as I already said in my previous comment.

                <dependency>
			<groupId>org.eclipse.angus</groupId>
			<artifactId>jakarta.mail</artifactId>
			<version>2.0.1</version>
		</dependency>

But we would like to use angus-mail as the source code is available in Github and that is needed for compliance activities. I do not see jakarta.mail source code in Github. Do you know where the source code for jakarta.mail has been hosted? How to bind the jakarta.mail-api and angus-mail? Some how it is not finding the implementation.

@jbescos
Copy link
Member

jbescos commented Feb 10, 2023

jakarta.mail sources are here: https://github.com/jakartaee/mail-api

You don't have to do anything to bind jakarta.mail-api with angus-mail. They must exist in the modulepath/classpath and thats all. If it is not working, it could be related to some issue with the classloaders, or simply angus-mail is not in the modulepath/classpath.

Is your app an standalone application, or is it deployed in a web container like Weblogic, Websphere?. What is the JRE that you are using?.

@viragpurnam
Copy link
Author

Hi @jbescos, https://github.com/jakartaee/mail-api this link has source code for just the api. Not the implementation.
Application is standalone and we are using java 11.

@jbescos
Copy link
Member

jbescos commented Feb 10, 2023

The implementation is already in this project where you are creating this issue:
https://github.com/eclipse-ee4j/angus-mail

org.eclipse.angus:jakarta.mail comes from this module of here. It creates a jar file containing the implementation (of angus-mail) and the jakarta.mail-api.

Could you check that angus-mail is in the classpath/modulepath of your application when it is executed?. It seems it is not there.

@viragpurnam
Copy link
Author

Thanks @jbescos. I am checking that. I will update you.

@viragpurnam
Copy link
Author

Hi @jbescos, Thanks a lot for your help. I feel I can use the below mentioned dependencies in my application as suggested by you. It works fine.

                <dependency>
			<groupId>org.eclipse.angus</groupId>
			<artifactId>jakarta.mail</artifactId>
			<version>2.0.1</version>
		</dependency>

@jmehrens
Copy link
Contributor

Closing this with no changes required to the code base. Shouldn't have to note this in the changes.txt because no commits were issued.

@ole1986
Copy link

ole1986 commented Mar 23, 2023

Possible reason for the mentioned issue can also be when calling the send mail method in an asynchrone thread

@turboezh
Copy link

Sorry for commenting closed issue.
I found that sending a mail from a ForkJoinPool thread in a packaged jar (Spring Boot) causes Not provider of jakarta.mail.util.StreamProvider was found. Maybe it could be related.

@vionta
Copy link

vionta commented Nov 27, 2023

Hi,
I’m getting this weird error.

I was getting the “java.lang.IllegalStateException: Not provider of jakarta.mail.util.StreamProvider was found”. The code worked before jakarta/angus update and also works in the IDE but not in the system (ant task + zulu 17).

I assumed there were classpath issues so I checked everything I could think off, checked several versions, major class versions (52), everything on a single jar (maven shade plugin). The class was there (org.eclipse.angus.mail.util.MailStreamProvider), opened the jar and checked.

So this is what I saw. I verified that I could add the name of the stream provider to the system properties and change the FactoryFinder strategy to a newInstance, but this also didn’t work.

System.setProperty("jakarta.mail.util.StreamProvider", "org.eclipse.angus.mail.util.MailStreamProvider");

Both Service based location (factoryFromServiceLoader) and newInstance are not working on FactoryFinder find method. I add code to test the problem and output below this lines where it seems that the class is there but the ServiceBasedLocation and instance is failing.

For me, after what I saw, I can download a copy of the jar and force regular old style forName + newInstance on FactoryFinder newInstance.

At the end it may probably be a simple classloading problem, a typpo or similar. I couldn’t find it. Hope that this is helpful somehow.
If you want me to check the changes and propose and update I would be pleased.

Kind Regards.

LOG
INFO: Delete Mode : false
WARNING: Testing class loading
WARNING: Trying the Service Loader code from FactoryFinder Class on the environment
WARNING: ServiceLoader.load does not return any results
WARNING: Trying the newInstance code from Factory Finder
WARNING: Using loadClass:
SEVERE: New Instance also didn't suceed.
SEVERE: java.lang.ClassNotFoundException: org.eclipse.angus.mail.util.MailStreamProvider
WARNING: Trying a simple new clause:
WARNING: With a new clause: org.eclipse.angus.mail.util.MailStreamProvider@146044d7
WARNING: WUT (): org.eclipse.angus.mail.util.MailStreamProvider@146044d7
WARNING: Trying a simple forName (Deprecated) newInstance
WARNING: Class For Name Instance Class: org.eclipse.angus.mail.util.MailStreamProvider@1e9e725a
WARNING: Is the instance assignable from StreamProvider: true
WARNING: Trying getConstructor newInstance:
WARNING: It works : org.eclipse.angus.mail.util.MailStreamProvider@15d9bc04
WARNING: But with : classLoader.loadClass
SEVERE: Does not work
SEVERE: java.lang.ClassNotFoundException: org.eclipse.angus.mail.util.MailStreamProvider
WARNING: ****
WARNING: Following with usual code : Session session = Session.getInstance(getProps(), null);
java.lang.IllegalArgumentException: Cannot instance org.eclipse.angus.mail.util.MailStreamProvider
at jakarta.mail.util.FactoryFinder.newInstance(FactoryFinder.java:77)

Testing Code
private void logServiceLoader() {
try {
LOG.warn("Testing class loading");
LOG.warn("Trying the Service Loader code from FactoryFinder Class on the environment");
ServiceLoader sl = ServiceLoader.load(jakarta.mail.util.StreamProvider.class);
Iterator iter = sl.iterator();
if (iter.hasNext()) {
LOG.warn("Looking for Service Instance with JDK (Zulu 17) ServiceLoader :");
LOG.warn("Found: " + iter.next().getClass());
} else {
LOG.warn("ServiceLoader.load does not return any results");
}
} catch (Exception e) {
LOG.error(e);
}

	LOG.warn("Trying the newInstance code from Factory Finder");
	ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	Class clazz = null;
	try {
		if (classLoader == null) {
			LOG.warn(" Using class forName on org.eclipse.angus.mail.util.MailStreamProvider : ");
			clazz = (Class) Class.forName("org.eclipse.angus.mail.util.MailStreamProvider");
		} else {
			LOG.warn(" Using loadClass: ");
			clazz = (Class) classLoader.loadClass("org.eclipse.angus.mail.util.MailStreamProvider");
		}
		LOG.warn(" Found Class: " + clazz);
		Object o = clazz.getConstructor().newInstance();
		LOG.warn(" Instance: " + o);
	} catch (ReflectiveOperationException e) {
		LOG.error("New Instance also didn't suceed.");
		LOG.error(e);
	}

	try {
		LOG.warn("Trying a simple new clause: ");
		org.eclipse.angus.mail.util.MailStreamProvider msp = new MailStreamProvider();
		LOG.warn("With a new clause: " + msp);
		LOG.warn("WUT (<x><x>): " + msp);

	} catch (Exception e) {
		LOG.error(e);
	}

	try {
		LOG.warn("Trying a simple forName (Deprecated) newInstance");
		Class<?> classFromforName = Class.forName("org.eclipse.angus.mail.util.MailStreamProvider");
		Object newInstance = classFromforName.newInstance();
		LOG.warn("Class For Name Instance Class: " + newInstance);
		boolean assignableFrom = jakarta.mail.util.StreamProvider.class.isAssignableFrom(newInstance.getClass());
		LOG.warn("Is the instance assignable from StreamProvider: " + assignableFrom);
		LOG.warn("Trying getConstructor newInstance: " );
		LOG.warn(" It works : " + classFromforName.getConstructor().newInstance());
		LOG.warn(" But with : classLoader.loadClass " );
		Class<?> loadClass = classLoader.loadClass("org.eclipse.angus.mail.util.MailStreamProvider");
		LOG.warn(" .. getting instance : "+loadClass.getConstructor().newInstance());
		 
	} catch (Exception e) {
		LOG.error(" Does not work ");
		LOG.error(e);
	}
	LOG.warn(" **** ");
	LOG.warn(" Following with usual code : Session session = Session.getInstance(getProps(), null);");

}

image

image

@jmehrens
Copy link
Contributor

@ole1986, @turboezh @vionta
PR 701 in JakartaMail should fix this issue that you are seeing with the async.

jakartaee/mail-api#701

@yoruritchie
Copy link

com.sun.mail jakarta.mail 2.0.1 com.sun.activation jakarta.activation 2.0.1

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

7 participants