Spring Integration – Session 2 – More Hello Worlds

This is a follow up to Spring Integration Session 1

The first session was a simple Hello World application using Spring Integration. I want to take it a little further by considering a few more scenarios around it.

So the first change to the Hello World application is to add in a Gateway component. To quickly revisit the earlier test program:

package org.bk.si.helloworld.hw1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("helloworld.xml")
public class HelloWorldTest {
 
 @Autowired
 @Qualifier("messageChannel")
 MessageChannel messageChannel;

 @Test
 public void testHelloWorld() {
  Message<String> helloWorld = new GenericMessage<String>("Hello World");
  messageChannel.send(helloWorld);
 }
}

In the lines highlighted above, the test is dependent on a Spring Integration specific component – a Message Channel, and in the test an explicit Spring Integration Message is constructed and sent to the Message Channel. There is a little too much coupling with Spring Integration which is the Messaging System here.

A Gateway component provides a facade to the messaging system, shielding the user application(in this case the Unit test) from the details of Messaging System – the messaging channel, Message and explicit sending of a message.

An example first to illustrate how the test will look with a Gateway component in place:

package org.bk.si.helloworld.hw2;

import org.junit.Test;
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;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("helloworld.xml")
public class HelloWorldTest {

 @Autowired Greeter greeter;

 @Test
 public void testHelloWorld(){
   this.greeter.sendGreeting("Hello World");
 }
}

The Greeter interface above is the Gateway component. Now that this component has been introduced there is no dependency to Spring Integration in this test – there is no mention of Message, Message Channel in the code at all.

The Gateway component is also a very simple Java Interface defined this way:

package org.bk.si.helloworld.hw2;

public interface Greeter {
 public void sendGreeting(String message);
}

So now the question is who takes care of creating the messaging and sending the message to a message channel – it is through Spring Integration configuration:

<?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:int="http://www.springframework.org/schema/integration"
 xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
  http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


 <int:channel id="messagesChannel"></int:channel>
 
 <int:gateway service-interface="org.bk.si.helloworld.hw2.Greeter" default-request-channel="messagesChannel"></int:gateway>
 
 <int-stream:stdout-channel-adapter channel="messagesChannel" append-newline="true"/>
 

</beans>

The highlighted line above creates the Gateway component out of the Greeter interface, a proxy is created in the background which handles everything that was being done explicitly earlier – creating the messaging and sending the message to the message channel.

Now to add a little more complexity to the Hello World sample:

Consider the following test:

package org.bk.si.helloworld.hw3;

import org.junit.Test;
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;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("helloworld.xml")
public class HelloWorldTest {

 @Autowired Greeter greeter;

 @Test
 public void testHelloWorld(){
  System.out.println("Started..");
  long start = System.nanoTime();
  for (int i=0;i<10;i++){
   this.greeter.sendMessage(String.format("Hello World %d",i));
  }
  System.out.println("Completed..");
  System.out.println(String.format("Took %f ms", (System.nanoTime()-start)/10e6));
 }
}

This is same as the previous unit test, except that in this case the “Hello World” message is being dispatched 10 times. The supporting Spring Integration configuration file is the following:

<?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:int="http://www.springframework.org/schema/integration"
 xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
  http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


 <int:publish-subscribe-channel id="messagesChannel"/>
 <int:gateway service-interface="org.bk.si.helloworld.hw3.Greeter" default-request-channel="messagesChannel"></int:gateway>
 
 
 <int-stream:stderr-channel-adapter channel="messagesChannel" append-newline="true"/>
 <int-stream:stdout-channel-adapter channel="messagesChannel" append-newline="true"/>
 
</beans>

If I run this test now, the output is along these lines:

The lines in red are being printed to syserr and in black are being printed to sysout.

So the question is why are some of them going to sysout and some of them going to syserr and why not to both?

The answer is because of the type of channel – “messagesChannel” above is a “Direct Channel” in the Spring Integration terminology and has “Point to point” semantics. The point-to-point semantics basically means that when a message comes into the Messaging Channel, only 1 receiver gets the message – so in this case either the standard out adapter OR the standard err adapter ends up printing the message that is coming into the message channel.

So to print to both adapters, the fix is to simply change the semantics of the channel – instead of a Point to Point channel, make it a Publish-Subscribe channel, which is a channel broadcasting out a message to multiple receivers. The change is very simple using Spring Integration:

file:/C:/learn/scratch/target/test-classes/org/bk/htmlencode/content.txt
<?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:int="http://www.springframework.org/schema/integration"
 xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
  http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


 <int:publish-subscribe-channel id="messagesChannel"/>
 <int:gateway service-interface="org.bk.si.helloworld.hw3.Greeter" default-request-channel="messagesChannel"></int:gateway>
 
 
 <int-stream:stderr-channel-adapter channel="messagesChannel" append-newline="true"/>
 <int-stream:stdout-channel-adapter channel="messagesChannel" append-newline="true"/>
 
</beans>

The output now will be the messages being printed to BOTH sysout and syserr

So this completes the introduction to a Gateway component, Direct Channel and Publish Subscribe channel.

Reference: Spring Integration – Session 2 – More Hello Worlds from our JCG partner Biju Kunjummen at the all and sundry blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


+ 9 = eleven



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close