Session.getSession Method throws NoSuchProviderException.
Problem arises when working with different classloaders.
Looking at the source code: It is not taken into account that the same classes may have been loaded in different class loaders.
We may find the class but not the constructor.
The class may be available in both the "application" class loader and the "system" class loader. The current implementation first tries the application CL then the system CL.
However when searching for the Constructor the classloader is no longer taken into account. The code:
Class[] c = {javax.mail.Session.class, javax.mail.URLName.class};
Constructor cons = serviceClass.getConstructor(c);
Object[] o = {this, url};
service = cons.newInstance(o);
will not find the constructor. since the classes in "c" were loaded in a different class loader.
to solve the issue: if the consturctor was not found with the serviceClass from the application class loader try the serviceClass from the system class loader before throwing an exception:
I propose to change the code to something like:
// find the provider class
ClassLoader ccl = getContextClassLoader();
if (ccl != null)
try {
serviceClass1 = ccl.loadClass(provider.getClassName());
} catch (ClassNotFoundException ex) { }
try {
serviceClass2 = cl.loadClass(provider.getClassName());
} catch (Exception ex1) {}
try {
serviceClass3 = Class.forName(provider.getClassName());
} catch (Exception ex) {}
// construct an instance of the class
if (serviceClass1 != null)
try {
Class[] c = {javax.mail.Session.class, javax.mail.URLName.class};
Constructor cons = serviceClass1.getConstructor(c);
Object[] o = {this, url};
service = cons.newInstance(o);
} catch (Exception ex) {}
if (service == null && serviceClass2 != null)
try {
Class[] c = {javax.mail.Session.class, javax.mail.URLName.class};
Constructor cons = serviceClass2.getConstructor(c);
Object[] o = {this, url};
service = cons.newInstance(o);
} catch (Exception ex) {}
if (service == null && serviceClass3 != null)
try {
Class[] c = {javax.mail.Session.class, javax.mail.URLName.class};
Constructor cons = serviceClass3.getConstructor(c);
Object[] o = {this, url};
service = cons.newInstance(o);
} catch (Exception ex) {}
if (service == null)
throw new NoSuchProviderException(provider.getProtocol());