Okay All,

I have worked quite a lot on this issue, and will try to explain what my current findings are, so that anyone else trying to get JavaMail working can avoid the pitfalls. I have tested several versions (snapshots, and an M5 release candidate) and can only conclude that JavaMail API support isn't complete yet. If it were complete, you would be able to do the following:

In your geronimo-application.xml deployment plan add a dependency to the Geronimo Mail component:

   <dependency>
     <uri>geronimo/jars/geronimo-mail-1.0-M5.jar</uri>
   </dependency>

And Configure two GBeans:

   <gbean name="JavaMailProtocol.smtp"
      class="org.apache.geronimo.mail.SMTPTransportGBean">
      <attribute name="host">192.168.10.10</attribute>
   </gbean>

   <gbean name="mail/MailSession"
     class="org.apache.geronimo.mail.MailGBean">
     <attribute name="transportProtocol">smtp</attribute>
     <attribute name="useDefault">false</attribute>
     <attribute name="debug">true</attribute>
<reference name="Protocols"><name>JavaMailProtocol.smtp</name></reference>
   </gbean>

Then in a Stateless Session Bean's Object JavaDocs you can put this XDoclet tag:

* @ejb.resource-ref description="JavaMail Resource"
*   res-ref-name="mail/MailSession"
*   res-type="javax.mail.Session" res-auth="Container"
*   res-sharing-scope="Shareable"

Or, if you're still using Deployment Descriptors directly, something like the following in your ejb-jar.xml would work:

        <resource-ref >
           <description><![CDATA[JavaMail Resource]]></description>
           <res-ref-name>mail/MailSession</res-ref-name>
           <res-type>javax.mail.Session</res-type>
           <res-auth>Container</res-auth>
           <res-sharing-scope>Shareable</res-sharing-scope>
        </resource-ref>

Okay, so why in the world doesn't this work? Well, there's no actual providers available in Geronimo to support the SMTP protocol. So, what you end up with is an execption that looks like this:

javax.mail.NoSuchProviderException: Unable to locate provider for protocol: smtp

       at javax.mail.Session.getProvider(Session.java:225)
       at javax.mail.Session.getTransport(Session.java:331)
       at javax.mail.Session.getTransport(Session.java:320)

What's nice is the Geronimo developers have gone through and implemented the javax.mail.Session class and if there were some providers available it would be possible to tell Geronimo's Mail API about them and have them used. I've confirmed that it would get that far, if there were any.

So, why not use the JavaMail reference implementation from Sun? You could personally do so, yes, download it, put its jars into the Geronimo repository and you'd be able to do just that. Personally I downloaded the JavaMail mail.jar and JAF activation.jar and put them into repository/javamail/jars/ under my Geronimo server root. Then I added the following dependencies before the geronimo-mail dependency in my geronimo-application.xml deployment plan like so:

   <dependency>
     <uri>javamail/jars/mail.jar</uri>
   </dependency>

   <dependency>
     <uri>javamail/jars/activation.jar</uri>
   </dependency>

   <dependency>
     <uri>geronimo/jars/geronimo-mail-1.0-M5.jar</uri>
   </dependency>

Now, when I write code like the following in my SLSB bean, it gives me a Session and I can use it to get a transport and send mail:

       InitialContext ctx = null;
       try {
           ctx = new InitialContext();

           javax.mail.Session session =
               (Session)ctx.lookup("java:comp/env/mail/MailSession");

           MimeMessage mes = new MimeMessage(session);
           mes.setFrom(InternetAddress.parse("[EMAIL PROTECTED]")[0]);
           mes.setRecipients(RecipientType.TO,"[EMAIL PROTECTED]");
           mes.setSubject("Testing");
           mes.setSentDate(new Date());

           mes.setContent(body,"text/plain");
           mes.saveChanges();
           Transport transport = session.getTransport();
           transport.connect();
transport.sendMessage(mes,InternetAddress.parse("[EMAIL PROTECTED]"));
           transport.close();
       } catch (Throwable ex) {
           ex.printStackTrace();
       } finally {
           if (ctx != null) ctx.close();
       }

This looks easy enough. But there are problems with this. What's actually happening behind the scenes here is that the $getResource() method of the MailGBean is being called to obtain a javax.mail.Session instance. MailGBean makes a fairly fatal mistake in how it sets up the Session's default Properties, however. Sun's JavaMail will not accept any properties that aren't Strings when it goes to parse things. So although you can see that I set the attribute 'debug' to 'true' in the MailGBean configuration, above, it is actually converted to a Boolean object, and that object is put into the properties. And Sun's JavaMail ignores it because it's not a String.

So that means that although it's nice to have the MailGBean and associated ProtocolGBean subclasses, the way they build the Properties for the Session isn't compatible with Sun's JavaMail implementation, so you can't use it.

So that leaves me with no alternative, at this time, than to add the JavaMail dependencies, and use Sun's JavaMail API directly to obtain sessions through the javax.mail.Session.getDefaultInstance() method instead of the more typical resource-ref and InitialContext.lookup().

As I say, this is how it is with the current state of Geronimo, days before an M5 release. I'm just reporting... I know it'll get fixed up soon anyway.

Cheers.

-Neal

Reply via email to