geronimo-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeremias Maerki <>
Subject Trouble with Geronimo's javax.mail under OSGi
Date Mon, 31 May 2010 15:52:39 GMT
I'd like to share my experience with the Geronimo javax.mail bundles.
I've had to resort to a work-around in the end to get this to work after
spending half a day tracking down the problem.

I have an OSGi-based application and only use some Geronimo bundles. I'm
not actually running Geronimo. I've installed the following bundles in
my Apache Felix Karaf instance:

- geronimo-javamail_1.4_spec-1.7.jar
- geronimo-javamail_1.4_provider-1.8.jar
- geronimo-osgi-registry-1.0.jar

What I'm building is a bundle that forwards certain events from the
EventAdmin to e-mail. I've enabled debug output so I get some idea
what's going on in the background. When an event is received, I can see
that the provider information is found and loaded from the "provider"
bundle (ID 185 in this case).

> Loading META-INF/javamail.providers from bundle://185.0:1/META-INF/javamail.default.providers

But when I'm trying to send an e-mail, I get this exception:

> 17:25:12,615|ERROR| Thread-85    | EMailAdapter                     |
 127 | Error sending e-mail: Unable to load class for provider: protocol=smtp; type=javax.mail.Pr
> ovider$Type@10c60d5; class=org.apache.geronimo.javamail.transport.smtp.SMTPTransport;
vendor=Apache Software Foundation;version=1.0
> javax.mail.NoSuchProviderException: Unable to load class for provider: protocol=smtp;
type=javax.mail.Provider$Type@10c60d5; class=org.apache.geronimo.javamail.transport.smtp.SMTPTransport;
> che Software Foundation;version=1.0
>         at javax.mail.Session.getService(
>         at javax.mail.Session.getTransport(
>         at javax.mail.Session.getTransport(
>         at javax.mail.Session.getTransport(
>         at javax.mail.Transport.send(
>         at javax.mail.Transport.send(
>         at
>         at org.apache.felix.eventadmin.impl.tasks.HandlerTaskImpl.execute(
>         at org.apache.felix.eventadmin.impl.tasks.SyncDeliverTasks$
>         at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$ Source)
>         at
> Caused by: java.lang.ClassNotFoundException: org.apache.geronimo.javamail.transport.smtp.SMTPTransport
>         at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(
>         at org.apache.felix.framework.ModuleImpl.access$100(
>         at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(
>         at java.lang.ClassLoader.loadClass(
>         at java.lang.Class.forName0(Native Method)
>         at java.lang.Class.forName(
>         at org.apache.geronimo.osgi.locator.ProviderLocator.loadClass(
>         at javax.mail.Session.getService(
>         ... 10 more

After some debugging, I found that while the providers are detected
properly, they are not loaded properly. Session.getClassLoader() checks
if there's a ContextClassLoader in the current thread which is what's
present in my case. The ClassLoader is a sun.misc.Launcher$AppClassLoader@601bb1
which seems to be the one with which Felix Karaf is started. So Session.getClassLoader()
takes the first ClassLoader it finds. Session.getService then tries to
actually load that class using ProviderLocator.loadClass(String, Class,
ClassLoader) which simply uses the given ClassLoader to load the class.
Since the Launcher$AppClassLoader doesn't see the classes in the
provider bundle, I get the ClassNotFoundException.

In the end I had to resort to a work-around: I've put the spec and
provider JARs in the endorsed directory and mapped the javax.mail.*
packages to the OSGi frameworks classloader. With this done, I get the
following in debug output and sending e-mail works:

> Loading javamail.default.providers from jar:file:/C:/Dev/..../karaf/endorsed/geronimo-javamail_1.4_provider-1.8.jar!/META-INF/javamail.default.providers

Obviously, that's not the nicest solution.

I've looked into loading classes using the standard SPI mechanism
(META-INF/services) under OSGi myself with [1], so I know a few things
about how this can be done. Essentially, I think MailProviderRegistry
needs to store the Bundle besides the URL to the javamail*.providers so
it can later load the provider classes using that Bundle's ClassLoader.
But that will mean extending the Provider class so it can carry the
Bundle for the Session.getService() method to load the providers.

So far, I haven't made any changes to geronimo-javamail_1.4_spec because
I wanted to get some input from the authors of that code. Maybe there's
a better way to do this. I'm also wondering why noone else seems to be
having that problem. I haven't found anything that fits exactly to my
problem on the net.

Any thoughts on this are appreciated.


Jeremias Maerki

View raw message