Basics of Spring Integration

Introduction to Basics of Spring Integration

With growing business needs and the number of components interacting to each other in a wide business setup, there arises a need for integrating the systems effectively. A traditional approach of integrating various systems is to connect each system with the remaining systems. This precisely means that if we have N systems to integrate, there would be N-1 connections from each system. Here we try to achieve this using Spring Integration.

Assumptions made while writing this blog:

  • You have a basic understanding of Spring framework and dependency injection.
  • You are not looking for a comparative study of Apache Camel and Spring Integration

A note to the reader: This is the simplest possible example to introduce Spring Integration and other use-cases will follow in subsequent blogs on the same topic and tag.

Problem

If we understand this, then each system in the setup will need to know N-1 connection configuration to effectively communicate with any system in the environment. If N is a smaller number, this makes sense. But think of the scenarios where N is more than hundred.

Pictorial representation of the tradition integration approach

integration_traditional

Solution

There are various integration frameworks available which help us integrate our systems in such a way that each system just need to know one connection configuration to communicate with any other system in the enterprise setup.

Architecture

The below image tries to explain how we achieve the same using integration framework. The systems now communicate to an integration system, which handles and makes sure that the messages reach the right systems or the systems entitled to receive the message pick them up.

integration_with_framework

Using Spring Integration

Just to keep it simple we need to understand the minimum terminologies which is used in integration framework:

  • Message – The atomic unit which can be sent across from one system to another. It contains a header and a payload.
  • Channel – These are the streams or pieces where some system/ channel will put data and the other system / channel will pick data from.
  • Router – This mostly works as a brain or rule engine which directs messages from one channel to another depending on certain criteria.

Implementation & Code

Requirements:
We will be needing the basic Spring jars in the classpath. Along with it we will also require Spring Integration jars. Spring Integration prior to 3.0 was a single spring-integration-core.jar.
Post Spring Integration 3.0 the whole library is segregated in various small modules. To get a comprehensive list please check Spring Integration website

Message

As mentioned above, Message plays an important role in Integration frameworks. So we will start with creating a Message class. Spring provides a GenericMessage, but we would like to create our own specialized Message class which will contain a payload of type String.

Now that we have our Message class in place, we can create numerous instances and send across the messages on the various channels which we are going to create next.

Channel

Spring offers a MessageChannel interface which can be implemented in various ways to create channels. In this case we will just use the MessageChannel implementations offered by Spring.

Below is the Spring configuration to declare the channels:

In the configuration above we declare an input channel on which messages will be placed and the router will direct to the respective output channels based on some configuration.

Also, we configure three output channels shouterOutput, messengerOutput, defaultOutput. All these channels have an underlying queue implementations and they are pollable. That precisely means that, these channels can be polled for messages available with them.

Router

Routers help in delegating the messages from the input channel(s) to the right output channel(s). Spring offers many such Router implementations, we will use the HeaderValueRouter implementation.

This router gives us a flexibility to define header parameters and set the values for these parameters. When the message arrives on the input channel which the router is listening to, it will evaluate the header value for the registered header parameter and place the message in the right output channel.

The configuration snippet below is from the above spring configuration xml. It declares a router with an id ‘router’, associates it with an input channel which has an id ‘input’ and it declares a header-name ‘testHeader’. Also, it maps the values of the header ‘testHeader’ to the appropriate output channels. Like below:

1) if the testHeader has a value shouter – it maps to the shouterOutput channel.
2) if the testHeader has a value messenger – it maps to the messengerOutput channel.
3) if the testHeader has a value default – it maps to the defaultOutput channel.

Now that the configuration is over, we will bootstrap spring and send messages on the input channel and in other section of the code we will try to read messages from different output channels and print the messages.

A sample run of the code will give us the below:


shouter received: [Payload=Spring Integration rocks ----- 0][Headers={timestamp=1373695864019, id=10b28e63-7b52-48b1-b70f-23ca51c34957, testHeader=shouter}]
messenger received: [Payload=Spring Integration rocks ----- 0][Headers={timestamp=1373695864019, id=6e03ad33-6600-4fcd-ba56-dabec04ca2df, testHeader=messenger}]
default received: [Payload=Spring Integration rocks ----- 1][Headers={timestamp=1373695864020, id=4494a27e-cf80-4a3a-994c-d0036eba6ec1, testHeader=default}]
default received: [Payload=Spring Integration rocks ----- 2][Headers={timestamp=1373695864020, id=556e387c-ee5b-4832-a8cf-cf7528e7aa19, testHeader=default}]
default received: [Payload=Spring Integration rocks ----- 3][Headers={timestamp=1373695864020, id=fa2f9a8b-ad6b-4951-b70b-c7f364e9dc61, testHeader=default}]
default received: [Payload=Spring Integration rocks ----- 4][Headers={timestamp=1373695864020, id=325a25d9-1eec-40aa-b4e2-a80465a2ef1b, testHeader=default}]
messenger received: [Payload=Spring Integration rocks ----- 5][Headers={timestamp=1373695864020, id=e0e8098c-2f5b-4f9c-8abf-92a0fa20091f, testHeader=messenger}]
default received: [Payload=Spring Integration rocks ----- 6][Headers={timestamp=1373695864020, id=003a6402-6d60-4484-84c3-bb964cb32670, testHeader=default}]
shouter received: [Payload=Spring Integration rocks ----- 7][Headers={timestamp=1373695864020, id=34f00e85-67be-4a87-94b3-c546f74e6068, testHeader=shouter}]
default received: [Payload=Spring Integration rocks ----- 8][Headers={timestamp=1373695864021, id=987a9ddd-f65e-42d0-91ce-baf6963e10d1, testHeader=default}]
default received: [Payload=Spring Integration rocks ----- 9][Headers={timestamp=1373695864021, id=b1a33957-1e3a-4b16-b828-ffd8fa832190, testHeader=default}]
messenger received: [Payload=Spring Integration rocks ----- 10][Headers={timestamp=1373695864021, id=7ed5e3e2-9cf0-4475-afc9-59e6311ea911, testHeader=messenger}]
default received: [Payload=Spring Integration rocks ----- 11][Headers={timestamp=1373695864021, id=95349528-7946-413d-881a-dabfae23d2e7, testHeader=default}]
default received: [Payload=Spring Integration rocks ----- 12][Headers={timestamp=1373695864021, id=56c7fc90-30d9-4639-8f21-5984c0c84f59, testHeader=default}]
default received: [Payload=Spring Integration rocks ----- 13][Headers={timestamp=1373695864021, id=ef9e5f8f-260f-41f7-9c24-f4fe43fedec1, testHeader=default}]
shouter received: [Payload=Spring Integration rocks ----- 14][Headers={timestamp=1373695864021, id=4c034221-72e5-4750-a104-69558d3eba0e, testHeader=shouter}]

 

Conclusion

This article touches the basics of Spring Integration and explains the terminologies used in any integration frameworks. There is much more with integration and best practices. Also, in the above code the sender and receiver are written in the same class and different threads. In real practice this can move to different projects, systems, web-services etc.

Please feel free to comment and ask questions is any. Stay connected and stay Subscribed