Rube Goldberg Spring Integration

Spring Integration provides a very nice abstraction over some complexities involved with Integrating systems together – Spring Integration fits the definition of a Facade perfectly from an Integration perspective- something that provides a simplified access to a complicated underlying system.

To illustrate this point, consider a simple system, which just takes in a message, and sends it back capitalized, call it the Echo Gateway:

public interface EchoGateway { 
    String echo(String message);
}

and a test for this:

@Test
 public void testEcho() {
  String response = echoGateway.echo('Hello');
  assertThat(response, is('HELLO'));
 }

Sounds simple so far, an implementation using spring integration would take in the ‘message’ and ‘transform’ it by converting to its upper case and returning the enhanced message.

<?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'
 xsi:schemaLocation='
  http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd'>
  
  <channel id='requestChannel'/>
  
  <gateway id='echoGateway' service-interface='rube.simple.EchoGateway' default-request-channel='requestChannel' />
  
  <transformer input-channel='requestChannel' expression='payload.toUpperCase()' />  
  
</beans:beans>

Works beautifully!!

The beauty of Spring Integration is that even if the Integration scenario grows complex, the facade that it presents back to the application continues to remain simple,

Consider a Rube Goldberg integration scenario:

First a diagram to describe the convoluted flow:

So what exactly does it do:

  • It takes in a message of this type – ‘hello from spring integ’,
  • splits it up into individual words(hello, from, spring, integ),
  • sends each word to a ActiveMQ queue,
  • from the queue the word fragments are picked up by a enricher to capitalize each word,
  • placing the response back into a response queue,
  • It is picked up, resequenced based on the original sequence of the words,
  • aggregated back into a sentence(‘HELLO FROM SPRING INTEG’) and
  • returned back to the application.

This is how a Spring Integration configuration for this kind of flow would look like:

<?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:int-jms='http://www.springframework.org/schema/integration/jms'
 xmlns:beans='http://www.springframework.org/schema/beans'
 xsi:schemaLocation='
  http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
  http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
  http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms-2.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd'>
  
  <beans:import resource='broker.xml'/>

  <channel id='requestChannel'>
   <queue/>  
  </channel>
  
  <channel id='responseChannel'>
   <queue/>
  </channel>

  <gateway id='echoGateway' service-interface='rube.complicated.EchoGateway' default-request-channel='requestChannel' default-reply-channel='responseChannel' default-reply-timeout='5000' />
  
  <channel id='toJmsOutbound'/>
  
  <splitter input-channel='requestChannel' output-channel='toJmsOutbound' expression='payload.split('\s')'>
  </splitter>
  
  <channel id='sequenceChannel'>
  </channel>

  <int-jms:outbound-gateway request-channel='toJmsOutbound' reply-channel='sequenceChannel' request-destination='amq.outbound' extract-request-payload='true' />

  <channel id='enhanceMessageChannel'/>
  <channel id='toReplyQueueChannel'/>
  
  <int-jms:inbound-gateway request-channel='enhanceMessageChannel' request-destination='amq.outbound' reply-channel='toReplyQueueChannel'/>

  <transformer input-channel='enhanceMessageChannel' expression='(payload + '').toUpperCase()' output-channel='toReplyQueueChannel'/>
  
  <resequencer input-channel='sequenceChannel' output-channel='aggregateChannel' release-partial-sequences='false'></resequencer>
  
  <aggregator input-channel='aggregateChannel' output-channel='responseChannel'  expression='T(com.google.common.base.Joiner).on(' ').join(![payload].toArray())'/>
  
  <poller id='poller' fixed-delay='500' default='true'/>
  
</beans:beans>

There is so much complexity in this flow(hence the Rube Goldberg), however the facade that Spring Integration provides to the application continues to remain very simple.

@Test
 public void testEcho() throws Exception{
  String amessage = 'Hello from Spring Integration';
  
  String response = echoGateway.echo(amessage);
  assertThat(response, is('HELLO FROM SPRING INTEGRATION'));
 }

This in my mind is the essence of Spring Integration

I have a github repository with this code at https://github.com/bijukunjummen/rg-si.git

Reference: Rube Goldberg Spring Integration from our JCG partner Biju Kunjummen at the all and sundry blog.

Share and enjoy!


© 2010-2012 Java Code Geeks. Licenced under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
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.