Enterprise Java

Introduction to Spring Integration Framework

As we are very much aware of the Spring Framework and JMS. In this article, we will get introduced to an enterprise integration framework known as Spring Integration. Spring Integration is an open source enterprise integration framework that enhances the capability of what Spring could have done alone. Built on Spring’s IoC, Spring Integration abstracts message sources and destinations, integrates the messages, routes and manipulates them, while integrating various components of the application environment.

The Message object that is used by Spring Integration to communicate, consists of the payload and header data. Payload contains the actual data, while header contains other metadata like id, timestamp, etc. Below diagrams illustrates the different components involved in a Spring Integration communication

So let’s create a sample Spring Integration application:

With a custom java interface as inbound gateway

  1. Create a new Maven project.
  2. Add the dependencies into the pom.xml file:
    <properties>
           <spring.version>4.0.0.RELEASE</spring.version>
           <jms.version>1.1-rev-1</jms.version>
           <activemq.version>3.1</activemq.version>
           <spring.integration.version>2.2.5.RELEASE</spring.integration.version>
           <junit.version>4.11</junit.version>
           <spring.test.version>3.2.3.RELEASE</spring.test.version>
    </properties>
    
    <!-- Spring Integration -->
    <dependency>
           <groupId>org.springframework.integration</groupId>
           <artifactId>spring-integration-core</artifactId>
           <version>${spring.integration.version}</version>
    </dependency>
    <dependency>
           <groupId>org.springframework.integration</groupId>
           <artifactId>spring-integration-jms</artifactId>
           <version>${spring.integration.version}</version>
    </dependency>
    
    <!-- Include Spring test -->
    <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-test</artifactId>
           <version>${spring.test.version}</version>
           <scope>test</scope>
    </dependency>
    
    <!-- Include JUnit -->
    <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>${junit.version}</version>
           <scope>test</scope>
    </dependency>
  3. Create the Student entity class, Student.java, as:
    package com.jcombat.entity;
     
    public class Student {
    	String name;
     
    	public Student(String name) {
    		this.name = name;
    	}
     
    	public String getName() {
    		return name;
    	}
    }
  4. Now let’s configure the spring integration components in a context file (name it as Test-context.xml):
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:jms="http://www.springframework.org/schema/jms" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:int-jme="http://www.springframework.org/schema/integration"
    	xmlns:int="http://www.springframework.org/schema/integration"
    	xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans   
    	    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    	    http://www.springframework.org/schema/context  
    	    http://www.springframework.org/schema/context/spring-context-3.0.xsd  
    	    http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
    	    http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
    	    http://www.springframework.org/schema/jms  
    	    http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
     
    	<!-- Enable annotations -->
    	<context:annotation-config/>
    	
    	<!-- Component scan to find all Spring components -->
     	<context:component-scan base-package="org.jcombat.integration"/>
     
    	<bean id="simpleMessageReceiver" class="com.jcombat.integration.DemoMessageReceiver" />
     
    	<!-- Define a request channel to communicate -->
    	<int:channel id="request" />
     
    	<int:outbound-channel-adapter channel="request" ref="simpleMessageReceiver" method="processMessage" />
    	
    	<int:gateway id="demoGateway" service-interface="com.jcombat.integration.DemoGatewayInterface"
    		default-request-channel="request"></int:gateway>
    	
    </beans>

    Message channels are something that encapsulate the actual data and decouple message producer from the consumer.

    Gateway is basically an entry/exit point for the messaging system. So if you have a messaging server in place, like ActiveMQ or TIBCO, the DefaultMessageListener acts as the inbound gateway, being the entry point to our messaging system.

    Service Activator is used to invoke a local service when the message arrives to the configured channel, in such a manner that the service doesn’t know it’s being invoked from a messaging system.

    An Adapter receives messages from an external messaging system (JMS, SFTP, etc.) and “adapts” it to the messaging system (as a Spring Integration Message<T>). The inbound JMS adapter takes in the incoming external messages and “adapts” it to the Spring Integration Message<T> type. And vice-versa: it takes a Spring Integration Message<T> and “adapts” it to the formats required by an external system.

    So, once a message comes in, via an Inbound Adapter, it flows from one component to another via Channels. Ultimately, it might be appropriate to write that message out somewhere. We can write the message using an Outbound Adapter.

  5. Now let’s create the gateway interface we have specified in the context, as:
    package com.jcombat.integration;
     
    import com.jcombat.entity.Student;
     
    public interface DemoGatewayInterface {
    	public void process(Student student);
    }
  6. Create a receiver class, which will finally receive the incoming message from the channel after being routed by the adapter.
    package com.jcombat.integration;
     
    import org.springframework.integration.Message;
     
    import com.jcombat.entity.Student;
     
    public class DemoMessageReceiver {
    	public void processMessage(Message<Student> message) {
    		Student student = message.getPayload();
    		System.out.println("Message Received - Student Name - " + student.getName());
    	}
    }
  7. This is it. Finally we need a client to make a call to the gateway interface method. Let’s do that using Spring Test Framework as:
    package com.jcombat.integration;
     
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     
    import com.jcombat.entity.Student;
    import com.jcombat.integration.DemoGatewayInterface;
     
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class Test {
     
    	@Autowired
    	private DemoGatewayInterface request;
     
    	@org.junit.Test
    	public void testIntegration() {
    		Student emp = new Student("Abhishek");
    		request.process(emp);
    	}
    }
  8. Add your application to the server and start the server.
  9. Navigate to the Test.java file we created in point 7 above and run it as JUnit test. Below is what we see logged in the IDE console:
     
    sprInt
  10. With Spring DefaultMessageListener as inbound gateway

    1. Create a new Maven project.
    2. Make sure the ActiveMQ server is up and running.
    3. The first and foremost thing is to make the entries into the pom.xml file. So it is the same as we have for the previous scenario.
    4. Let’s write the context file (jmsContext.xml) and configure the Spring Integration components as:
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
      	xmlns:jms="http://www.springframework.org/schema/jms" xmlns:p="http://www.springframework.org/schema/p"
      	xmlns:int-jme="http://www.springframework.org/schema/integration"
      	xmlns:int="http://www.springframework.org/schema/integration"
      	xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
      	xsi:schemaLocation="http://www.springframework.org/schema/beans   
      	    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
      	    http://www.springframework.org/schema/context  
      	    http://www.springframework.org/schema/context/spring-context-3.0.xsd  
      	    http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
      	    http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
      	    http://www.springframework.org/schema/jms  
      	    http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
       
      	<bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
      		<property name="brokerURL" value="tcp://localhost:61616" />
      	</bean>
       
      	<bean id="messageListenerContainer"
      		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
      		<property name="connectionFactory" ref="connectionFactory" />
      		<property name="destinationName" value="testQueue" />
      		<property name="maxConcurrentConsumers" value="1" />
      		<property name="concurrentConsumers" value="1" />
      		<property name="receiveTimeout" value="5000" />
      		<property name="recoveryInterval" value="60000" />
      		<property name="autoStartup" value="true" />
      	</bean>
       
      	<!-- Define a channel to communicate out to a JMS Destination -->
      	<int:channel id="inbound" />
      	<int:channel id="outbound" />
       
      	<bean id="simpleMessageListener" class="com.jcombat.listener.SimpleMessageListener" />
      	
      	<int-jms:message-driven-channel-adapter
      		id="jmsIn" container="messageListenerContainer" channel="inbound"
      		acknowledge="auto" />
       
      	<int:service-activator input-channel="inbound"
      		output-channel="outbound" ref="simpleMessageListener" method="onMessage" />
       
      	<int-jms:outbound-channel-adapter id="jmsOut"
      		channel="outbound" connection-factory="connectionFactory"
      		destination-name="sampleQueue" />
       
      </beans>
    5. Let’s load up the context on server start. To do that, make an appropriate entry into the web.xml file as:
      <web-app 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/web-app_3_0.xsd"
                              version="3.0">
                              
      	<context-param>
      		<param-name>contextConfigLocation</param-name>
      		<param-value>/WEB-INF/jmsContext.xml</param-value>
      	</context-param>
       
      	<listener>
      		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      	</listener>
      </web-app>
    6. Create the listener class, which will be finally receiving the message, as:
      package com.jcombat.listener;
       
      public class SimpleMessageListener {
       
      	public String onMessage(String message) {
      		System.out.println(message);
      		return message;
      	}
      }
    7. Time to run our application. So this should work as:
      1. Send a custom message to the testQueue:
         
        sprInt1
      2. The listener gets invoked, and it’s onMessage method gets executed, logging the incoming message to the IDE console as:
         
        sprInt2
      3. The message is passed on the outbound channel and via outbound adapter to the destination sampleQueue, as can be seen below:
         
        sprInt3
    8. Download the Source Code

      You can download the source code here.

      Reference: Introduction to Spring Integration Framework from our JCG partner Abhimanyu Prasad at the jCombat blog.

Abhimanyu Prasad

Abhimanyu is a passionate tech blogger and senior programmer, who has an extensive end-to-end development experience with wide range of technologies. He is the founder and administrator at jCombat.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Sri
Sri
8 years ago

Hi,

I am not able to figure out the org.springframework.integration.Message import. Did I miss anything?

Thanks,
Sri

Abhimanyu
8 years ago

Hi Sri,

It’s because of the improper artifact versions that you were using in your application. This post has been updated. Kindly re-check the pom.xml entries. It now has the pom artifact versions as well. Also, you can now download the source code.

Hope that helps!

Mounir
Mounir
8 years ago

Thanks for the post,

Can you upload code source , c’ant find it in dropbox

Regards,

Back to top button