geronimo-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeremias Maerki <...@jeremias-maerki.ch>
Subject Re: Trouble with Geronimo's javax.mail under OSGi
Date Tue, 01 Jun 2010 10:20:42 GMT
On 01.06.2010 11:56:03 Rick McGuire wrote:
> On 5/31/2010 11:52 AM, Jeremias Maerki wrote:
> > 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                     | wod.job.events.mail.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;
vendor=Apa
> >> che Software Foundation;version=1.0
> >>          at javax.mail.Session.getService(Session.java:494)
> >>          at javax.mail.Session.getTransport(Session.java:387)
> >>          at javax.mail.Session.getTransport(Session.java:347)
> >>          at javax.mail.Session.getTransport(Session.java:376)
> >>          at javax.mail.Transport.send(Transport.java:67)
> >>          at javax.mail.Transport.send(Transport.java:48)
> >>          at ch.jm.wod.job.events.mail.EMailAdapter.handleEvent(EMailAdapter.java:124)
> >>          at org.apache.felix.eventadmin.impl.tasks.HandlerTaskImpl.execute(HandlerTaskImpl.java:87)
> >>          at org.apache.felix.eventadmin.impl.tasks.SyncDeliverTasks$1.run(SyncDeliverTasks.java:228)
> >>          at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(Unknown
Source)
> >>          at java.lang.Thread.run(Thread.java:619)
> >> Caused by: java.lang.ClassNotFoundException: org.apache.geronimo.javamail.transport.smtp.SMTPTransport
> >>          at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:726)
> >>          at org.apache.felix.framework.ModuleImpl.access$100(ModuleImpl.java:60)
> >>          at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1629)
> >>          at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
> >>          at java.lang.Class.forName0(Native Method)
> >>          at java.lang.Class.forName(Class.java:247)
> >>          at org.apache.geronimo.osgi.locator.ProviderLocator.loadClass(ProviderLocator.java:195)
> >>          at javax.mail.Session.getService(Session.java:492)
> >>          ... 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.
> >    
> 
> I took a second look at how the ProviderLocator is handling this, and 
> this should be working without the OSGi registory.  However, it will 
> only work if you are using the mail uber jar rather than using the spec 
> and provider bundles separately.  That's really the intended way to use 
> these.  The combined jar can be found here:
> 
> http://repo1.maven.org/maven2/org/apache/geronimo/javamail/geronimo-javamail_1.4_mail/1.8/
> 
> This should work without installing the geronimo-osgi-registry bundle 
> first.
> 
> Rick

Thanks, Rick. I wasn't aware that there was a combined bundle. That's
definitely another way to work-around the provider problem as long as
you don't need additional providers. I can live with that. But the
problem with Session.getClassLoader() about the ContextClassLoader is
still getting in the way in my case. I've had to do the following to
make it work:

            ClassLoader bakCL = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(null);
            try {
                Transport.send(msg);
            } finally {
                Thread.currentThread().setContextClassLoader(bakCL);
            }

Just getting the first class loader that may fit is probably too easy.
In Apache XML Graphics Commons, we try multiple class loaders until we
really have to give up loading a particular provider class.

At least I now have a satisfying solution that doesn't have to resort to
providing javax.mail support via the endorsed mechanism.

<snip/>

Thanks,
Jeremias Maerki


Mime
View raw message