Written on
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?'
}
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).
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"
}
}
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>
class MyService {
static transactional = true
MessageChannel someMessageChannel
def void someOperation() {
// ...
someMessageChannel.send(...)
}
}
someMessageChannel.send(new GenericMessage<String>("my 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))
<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>
<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>