Getting started with Spring Integration v2 and Enterprise Integration Patterns – A Simple Example using File and Mail Adapters


I’ve recently had a requirement to do some Enterprise Integration stuff and tried out Spring Integration for it. I’ve found it to be simple, easy-to-use, and flexible. So, I thought of sharing it with you all.

Here’s the requirement: A daemon program should look for XML files in a particular directory every ‘n’ minutes and if a file is found, it should read the XML data from the file and send it to a mailbox.

It’s pretty doable with plain Java itself, but Spring Integration framework greatly simplifies this task with its’ rich set of adapters.

Here’s what Mark Fisher says about Spring Integration @ http://www.springsource.org/spring-integration

Spring Integration provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns. It enables lightweight messaging within Spring-based applications and supports integration with external systems via declarative adapters. Those adapters provide a higher-level of abstraction over Spring’s support for remoting, messaging, and scheduling. Spring Integration’s primary goal is to provide a simple model for building enterprise integration solutions while maintaining the separation of concerns that is essential for producing maintainable, testable code.

Okay, let’s jump into the code straightaway. You can use this code as a kind of archetype and go ahead with your implementations. You always have Spring Integration Reference for your help! Btw, this example also guides you on the Spring configuration required to send emails through your Gmail account.

Download the source code of this example here.

SpringIntegrationDemoMain.java

package singz.samples.eai.springintegration;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/*
 * @author Singaram Subramanian
 */

public class SpringIntegrationDemoMain
{
 public static void main( String[] args )
 {
 // Instantiate Spring application context with the bean definitions
 // and the integration flow
 new ClassPathXmlApplicationContext("integration-context.xml");
 }
}

integration-context.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- @author Singaram Subramanian -->

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
 xmlns="http://www.springframework.org/schema/integration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:file="http://www.springframework.org/schema/integration/file"
 xmlns:mail="http://www.springframework.org/schema/integration/mail"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file-2.0.xsd http://www.springframework.org/schema/integration/mail http://www.springframework.org/schema/integration/mail/spring-integration-mail-2.0.xsd">

 <beans:bean id="mailTransformerBean"
 class="singz.samples.eai.springintegration.MailTransformer">
 <beans:property name="mailTo" value="XXX@gmail.com" />
 <beans:property name="mailFrom" value="XXX@gmail.com" />
 <beans:property name="mailSubject" value="Spring Integration - Test Mail" />
 </beans:bean>

 <beans:bean id="mailSender"
 class="org.springframework.mail.javamail.JavaMailSenderImpl">
 <beans:property name="host" value="smtp.gmail.com" />
 <beans:property name="port" value="587" />
 <beans:property name="username" value="XXX" />
 <beans:property name="password" value="XXX" />
 <beans:property name="javaMailProperties">
 <beans:props>
 <beans:prop key="mail.smtp.auth">true</beans:prop>
 <beans:prop key="mail.smtp.starttls.enable">true</beans:prop>
 </beans:props>
 </beans:property>
 </beans:bean>

 <channel id="filesIn" />
 <channel id="mailMsgTransformer" />
 <channel id="outboundMail" />

 <!-- Here's the Spring Integration flow -->

 <!-- This demo application flow starts with a file channel adapter that
 looks for XML files in a particular directory (C:\FileServer) every 5 seconds -->
 <file:inbound-channel-adapter channel="filesIn"
 directory="C:\FileServer" prevent-duplicates="true" filename-pattern="*.xml">
 <poller fixed-rate="5000" />
 </file:inbound-channel-adapter>

 <!-- This transformer component reads data from the XML file coming from
 filesIn channel and converts it to a String and passes that to another transformer
 component, MailMsgTransformer, which constructs a mail message out of it -->
 <file:file-to-string-transformer
 input-channel="filesIn" output-channel="mailMsgTransformer"
 delete-files="true" charset="UTF-8" />

 <transformer ref="mailTransformerBean" input-channel="mailMsgTransformer"
 method="transform" output-channel="outboundMail" />

 <!-- Sends the mail to the mailbox with the credentials defined by mailSender bean -->
 <mail:outbound-channel-adapter channel="outboundMail"
 mail-sender="mailSender" />

</beans:beans>

MailTransformer.java

package singz.samples.eai.springintegration;

import java.io.ObjectInputStream.GetField;
import java.util.Date;

import org.apache.log4j.Logger;
import org.springframework.integration.Message;
import org.springframework.mail.MailMessage;
import org.springframework.mail.SimpleMailMessage;

/*
 * @author Singaram Subramanian
 *
 * MailTransformer constructs a simple mail message out of the payload (XML data in this case)
 * that the incoming Message instance carries with it.
 */
public class MailTransformer {
 private String mailTo;
 private String mailFrom;
 private String mailSubject;

 private static Logger logger = Logger.getLogger(MailTransformer.class);

 public String getMailTo() {
 return mailTo;
 }

 public void setMailTo(String mailTo) {
 this.mailTo = mailTo;
 }

 public String getMailFrom() {
 return mailFrom;
 }

 public void setMailFrom(String mailFrom) {
 this.mailFrom = mailFrom;
 }

 public String getMailSubject() {
 return mailSubject;
 }

 public void setMailSubject(String mailSubject) {
 this.mailSubject = mailSubject;
 }

 public MailMessage transform(Message<?> message) {
 Object payload = message.getPayload();
 String mailText = (payload != null) ? payload.toString()
 : "File is empty";

 logger.info("XML payload data from the file: " + mailText);

 MailMessage msg = new SimpleMailMessage();

 msg.setTo(mailTo);
 msg.setFrom(mailFrom);
 msg.setSubject(mailSubject);
 msg.setSentDate(new Date());
 msg.setText(mailText);

 logger.info("Constructed the mail to be sent to the mailbox");

 return msg;
 }

}

An introduction to Spring Integration by Mark Fisher

 

About Enterprise Integration Patterns

Enterprise Integration Patterns is a book by Gregor Hohpe and Bobby Woolf and describes a number of design patterns for the use of enterprise application integration and message-oriented middleware. These patterns can be implemented without much coding through Apache Camel, Fuse Mediation Router or the maturing Spring Integration.

Here’s an excerpt from http://www.eaipatterns.com/ on Enterprise Integration,

Why Do We Need Integration?

Today’s business applications rarely live in isolation. Users expect instant access to all business functions an enterprise can offer, regardless of which system the functionality may reside in. This requires disparate applications to be connected into a larger, integrated solution. This integration is usually achieved through the use of some form of “middleware”. Middleware provides the “plumbing” such as data transport, data transformation, and routing.

What Makes Integration so Hard?

Architecting integration solutions is a complex task. There are many conflicting drivers and even more possible ‘right’ solutions. Whether the architecture was in fact a good choice usually is not known until many months or even years later, when inevitable changes and additions put the original architecture to test. Unfortunately, there is no “cookbook” for enterprise integration solutions. Most integration vendors provide methodologies and best practices, but these instructions tend to be very much geared towards the vendor-provided tool set and often lack treatment of the bigger picture, including underlying guidelines, principles and best practices.

Asynchronous Messaging Architectures

Asynchronous messaging architectures have proven to be the best strategy for enterprise integration because they allow for a loosely coupled solution that overcomes the limitations of remote communication, such as latency and unreliability. The trend towards asynchronous messaging has manifested itself in a variety of EAI suites as well emerging standards for reliable, asynchronous Web services. Unfortunately, asynchronous messaging is not without pitfalls. Many of the assumptions that hold true when developing single, synchronous applications are no longer valid. What is needed is vendor-independent design guidance on building robust integration architectures based on asynchronous messaging.

How can Patterns Help?

Patterns are a proven way to capture experts’ knowledge in fields where there are no simple “one size fits all” answers, such as application architecture, object-oriented design, or message-oriented integration . Each pattern poses a specific design problem, discusses the considerations surrounding the problem, and presents an elegant solution that balances the various forces or drivers. In most cases, the solution is not the first approach that comes to mind, but one that has evolved through actual use over time. As a result, each pattern incorporates the experience base that senior integration developers and architects have gained by repeatedly building solutions and learning from their mistakes. This implies that we did not “invent” the patterns; patterns are not invented, but rather discovered and observed from actual practice in the field.

About these ads

3 comments

  1. conzyor34 · · Reply

    Nice. That loop in the main routine will consume 100% of a single CPU doing no useful work. Your UNIX team is slapping their foreheads about now.

    1. Thanks Conzyor for pointing that out, I’ve corrected that. That indefinite while loop isn’t required at all in the main() routine.

      Thanks,
      Singaram.

  2. [...] by Josh Long in SpringSource News & Announcements Singaram Subramanian has written up a blog on how he was tasked with solving an email integration problem and decided to use Spring Integration. The blog details the code and approach and even talks a bit [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 26 other followers

%d bloggers like this: