Integration and Grails

In most applications, it is a common requirement to implement a mail sending mechanism. Indeed, there is the mail plugin [0] which achieves that use case by injecting a sendMail method in Grails artefacts:
 
sendMail {
  to "fred@g2one.com"
  subject "Hello Fred"
  body 'How are you?'
}
 
But maybe you already had the situation that you felt that this level of integration is not enough - maybe you wanted to use message pooling or you wanted to have multiple task executors processing the message queue from time to time. Luckily there exists an extension to the Spring Framework which is ment to handle such tasks: Spring Integration [1].

A Small Introduction to Spring Integration

Spring Integration is all about enabling messaging architectures in Spring-based applications. In this context, messaging does not mean sending e-mails. In a message-oriented middleware (MOM) software components communicate by sending packets of data. Each message has a producer (that part that generated the message) and one or more consumers (doing something with the data provided by the message). A Messaging System Compared to pure method invocations, a messaging communication always implies asynchrony - the producer thread typically does not wait for the consumers to get responses, it sends and forgets. But as the messaging system leverages transaction support, message persistency, pooling of messages, and various other services, using a messaging architecture is especially an option in integration scenarios with external systems (e.g. an SMTP server).

Adding Spring Integration as Dependency

A dependency to Spring Integration can simply be specified in the application's BuildConfig.groovy:
 
dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.

        // ...

   	compile('org.springframework.integration:spring-integration-mail:1.0.4.RELEASE')  {
          excludes "spring-aop", "spring-beans", "spring-context", "spring-context-support", "spring-core", "spring-tx"
        }
    }
 
Be aware that Grails itself has a dependency on multiple Spring modules, that is the reason why the code sample above explicitly excludes those modules. As you can see, there is a specific Spring Integration module for mail support with artefact-id spring-integration-mail which is used in this example. There are various extensions e.g. for RMI, HTTP, JMS etc. integration scenarios.

A simple configuration

As mentioned, producers, consumers and messages play a central role in messaging systems. Another important concept is called a channel. A channel is a logical pathway between a sender and its receivers. Spring Integration supports two conceptually different channel types: event-based and polling channels. Event-based channels are rather easy to understand. Whenever a message is sent on an event-based channel, the subscribers immediately receive that message. On the other side, polling channels poll the channel for new messages and if messages are found, those are handled by the associated consumers. Let us assume the use case for our application is to send mails in chunks - either the application sends chunks of 50 messages or it waits for a certain timeout to occur. First step is to create an integration.xml and to define a pollable channel in there:
 
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:mail="http://www.springframework.org/schema/integration/mail"
	xsi:schemaLocation="http://www.springframework.org/schema/beans ... ">

    <channel id="someMessageChannel"/>

</beans:beans>
 
The integration.xml file can simply be referenced by Grails resources.xml or resources.groovy. Per default such a declaration declares a org.springframework.integration.channel.DirectChannel bean. A direct channel is a point-to-point channel that supports execution of message operations in a single thread. As the someMessageChannel is a Spring bean it can be injected into Grails service classes:
 
class MyService {

  static transactional = true

  MessageChannel someMessageChannel

  def void someOperation()  {
    // ...

    someMessageChannel.send(...)
  }
}

 
The MessageChannel can now be used to send org.springframework.integration.core.Message instances:
 
  someMessageChannel.send(new GenericMessage<String>("my payload"))
 
In this case, the message simply has an instance of java.lang.String as payload, but the GenericMessage actually is generic and supports arbitrary classes. In our use case of sending mails, the application has to construct a more complicated message, including message headers in addition to the message payload:
 
    def headers = [:]

    headers.put MailHeaders.FROM, from
    headers.put MailHeaders.SUBJECT, subject
    headers.put MailHeaders.TO, receiver

    // create an instance of javax.mail.internet.MimeMessage

    // ...

    someMessageChannel.send(new GenericMessage<MimeMailMessage>(new MimeMailMessage(mimeMessage), headers))
 
This is the time we need to add another component to our configuration file: we need to add an SMTP adapter. An adapter acts as messaging client and invokes functionality of the adapted application or component. The Spring Integration Mail module provides an adapter that delegates to Spring's JavaMailSender. Thus in order to add get the mail adapter working, you need a mail sender in the application context:
 
  <channel id="someMessageChannel"/>

  <!-- mailSender bean needs to be configured somewhere in the application context... -->
  <mail:outbound-channel-adapter channel="someMessageChannel" mail-sender="mailSender"/>
</beans:beans>
 
Last step is to add polling capabilities to our someMessageChannel which can be done with some additional XML configuration:
 
  <channel id="someMessageChannel"/>

  <!-- mailSender bean needs to be configured somewhere in the application context... -->
  <mail:outbound-channel-adapter channel="someMessageChannel" mail-sender="mailSender">
    <poller max-messages-per-poll="50">
      <interval-trigger interval="30" time-unit="SECONDS"/>
    </poller>
  </mail:outbound-channel-adapter>
</beans:beans>
 
Please notice, in a real world example the application would probably not create a message instance which is tied to a MimeMessage. In place of adding the mail related information on message creation, one could use Transformer implementations to do that just before the mail adapter receives the message.

Conclusion

Spring Integration is a mighty Spring extension - if you are seriously developing Grails applications you should consider taking a look at it. Sending mail is only the peak of the iceberg - if you think especially of enterprise integration scenarios with other applications or external systems using a messaging system (and maybe a JMS messaging server) can enforce performance and reliability of applications. If you want to delve into the topic of enterprise integration patterns, take a look at [Amazon-Link, 4], btw Spring Integration's design is inspired by the patterns mentioned there.

[0] Grails Mail Plugin - http://www.grails.org/Mail+plugin
[1] Spring Integration Project Homepage
[2] Spring Integration in Central Maven Repo
[3] Enterprise Integration Patterns - Hohpe, Woolfe, et.al.