Blog

Monday, 23 July 2012

Reliable mail delivery in Seam

If you need to send emails form your application then there is nice seam-mail, a CDI extension. However frequently you need to assure that some email gets delivered. Let's consider registration process. User fills in their email and new password, the application should then send him mail with activation code. What if the mail server is currently down or for some other reason the mail cannot be delivered at the moment?
Should your application throw exception? Display error message and deny registration?

It would be best to create the account anyway and let user a bit longer for getting the email in their mailbox. Meanwhile our application should attempt to deliver the mail.

Simple solution is to put the mail into transactional JMS queue. MessageDrivenBeans could then attempt to get the message from queue and attempt to send it to mail server. We could easily configure the queue with redelivery time, delivery attempts and dead message queue (in case the mail cannot be delivered X times).

This is very easy with seam3-mailman library from IT Crowd. All you need to do is to add seam3-mailman.jar to your application, configure JMS queues on your server and 2 beans in the library.

For JBoss AS 7 log into jboss-admin and type:
/subsystem=messaging/hornetq-server=default/jms-queue=myAppMail:add(durable=true,entries=["queue/myAppMail"])
Now we need to configure CDI bean that is responsible for sending mail to queue:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="urn:java:ee"
       xmlns:mail="urn:java:org.jboss.seam.mail.core" xmlns:mailman="urn:java:pl.com.it_crowd.seam3.mailman"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd">


    <mail:MailConfig jndiSessionName="java:/myApp/mail/Default">
        <s:modifies/>
    </mail:MailConfig>

    <mailman:Mailman queueName="queue/myAppMail">
        <s:modifies/>
    </mailman:Mailman>

</beans>
Final step is to configure message driven bean that is shipped with the library. You can do that by adding ejb-jar.xml to your application:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">

    <enterprise-beans>
        <message-driven>
            <ejb-name>JMSMailListener</ejb-name>
            <ejb-class>pl.com.it_crowd.seam3.mailman.JMSMailListener</ejb-class>
            <activation-config>
                <activation-config-property>
                    <activation-config-property-name>destination</activation-config-property-name>
                    <activation-config-property-value>queue/myAppMail</activation-config-property-value>
                </activation-config-property>
            </activation-config>
        </message-driven>
    </enterprise-beans>

</ejb-jar>
That's it, now you can tune your queue for Dead Letter Queue, redelivery count and timeout and so on. seam3-mailman sources are available at https://github.com/it-crowd/seam3-mailman. Downloads are hosted in our Artifactory. For maven users:
<dependency>
    <groupId>pl.com.it-crowd.seam3.mailman</groupId>
    <artifactId>seam3-mailman</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>