Electronic data interchange was one of my major focuses over the course of my career. I worked with teams of developers to build applications that implement complex business process flows; parse, route and transform data; and interact with internal and external systems and services. For the most part we wrote the code to handle mediation, orchestration, and synchronous or asynchronous integration by hand. While we learned a great deal in the process, we also became mired in the task of maintaining and enhancing the platform we created rather than focusing on the core business logic. Furthermore, many of the problems we solved were already commonly solved by enterprise integration patterns and the integration frameworks which implement those patterns.
Spring Integration provides a framework to easily orchestrate your business logic as well as integrate with endpoints external to your application and/or organization. Like other Java integration frameworks, Spring Integration implements enterprise integration patterns, as well as implementing integration with various standard endpoints, and it does so in the same model the rest of the Spring framework uses. Basically, if you understand Spring, understanding Spring Integration comes naturally.
Spring Integration takes a modular approach to external system integration and there are several modules available including Mail, HTTP, Web Services, JDBC, Twitter, XMPP, SFTP, FTP, RSS, and many more. To use these modules, just include the appropriate jars on your classpath and the namespace references in your configuration. There is a complete list of modules at the end of this post.
Example
In this example, we’re going to implement a very common B2B pattern: retrieve, parse, transform, transmit. The configuration will retrieve a message from an inbound queue, parse it to determine what type of message it is, transform the message to the appropriate outbound format, and then transmit it to an endpoint. The message coming in the door will be either JSON, a domain object or something unknown and it will need to be posted to a JSON endpoint.
Dependencies
In order to build and run a Spring Integration project, we’ll need a few dependencies. At a minimum, we’ll need Spring Integration core, and then we’ll be able to pick and choose from a very long list of modules depending on what you’re building. For this example, we’ll be using core and http for REST calls. We’ll also use Jackson for JSON transformation.
Here’s the dependency configuration for Maven:
Configuration
With that out of the way, we can move on to configuration.
In Spring Integration 2.2 and up (current version is 4.0), we have several options to configure your integration including:
- Traditional Spring XML with Annotations
- Scala DSL
- Groovy DSL
- Java DSL (Community Provided)
For this example, we will use standard XML configuration as it’s straightforward and doesn’t require knowledge of Scala or Groovy.
Here’s the complete configuration. I’ll break down each section in detail below.
Channels
Note: I’ve declared all of my channels in one place for readability purposes only. This is not necessary.
First we declare all of the channels. Channels decouple your logical components, such that, each component only knows its own business logic—where to get its input and where to send its output. Each channel acts as a message queue with configurable queue depth and type.
Gateway
Next, we declare a gateway called “inboundGateway”. The purpose of the gateway is to provide a convenient way for messages to be sent into the request channels, while hiding all messaging specific code and decoupling the user from Spring Integration. In order to do that, the user provides a service-interface which defines the methods the user will use to interact with the gateway. Spring then generates a proxy based on that interface.
Gateways, in Spring Integration, come in many flavors depending on the modules you include. For example, spring-integration-ws contains web service gateways and spring-integration-http contains http gateways. Only the standard gateway provides the service-interface functionality.
The default-request-channel is where messages that pass through the gateway will be sent and the default-reply-timeout is 5000ms. When using an inbound gateway, always specify a reply-timeout. If you do not specify a timeout and you do not get a response or throw an exception, the thread will block, permanently.
Router
Here, we declare a payload-type-router with an input-channel pointing to “requestChannel” and its default-output-channel set to “deadLetterChannel”. This assumes, by default, that we cannot parse the request.
Inside the payload-type-router, we declare two mappings that indicate the two types we can parse. The first is a Person, a POJO, which it routes to the “objectToJsonChannel”. The second is a String, as all JSON objects are strings, and it routes directly to “outboundChannel”. This is effectively parsing the data by type. Spring Integration natively provides routers that can route by payload, header, or send data to a list of recipients. The user also has the ability to create dynamic routers using Spring Expression Language (SpEL).
Transformer
Next, we declare an object-to-json-transformer. You’ll notice from this configuration that we don’t tell Spring Integration anywhere how to do the transformation, we just provide the input-channel and output-channel, and just by having Jackson on the classpath, it figures out the rest.
Outbound Gateway
Lastly, we declare an http-outbound-gateway, specifying the URL, http-method, the reply-channel, and the response type of String as I’m expecting a JSON response.
Logging
Just for demonstration’s sake, we can define a logging-channel-adapter to automatically log everything that ends up on the outbound channel.
Code
To make the above configuration work, we need to write some code. First, we need to define my person domain object, which is a POJO containing name, email, age, and gender fields, and the appropriate getters and setters.
Next, we need to define the service-interface that is referenced in the gateway configuration, which is a standard interface with two methods that each take a single parameter, a string, or my Person domain object.
Here’s the interface:
Lastly, in order to actually use this configuration, we need a client that loads it, instantiates the gateway, and calls the methods defined in the service interface.
Here’s the incredibly simple client:
The client loads the application context and instantiates a RequestGateway, creates a person object and a JSON string and posts each according to the methods defined in the interface.
The output of these requests follows:
INFO : org.springframework.integration.handler.LoggingHandler – {“name”:”Bob Smith”,”email”:”bsmith@bobsmith.com”,”age”:77,”gender”:”MALE”}
INFO : org.springframework.integration.handler.LoggingHandler – { name: “Troy McLure”, age: “-1″, email: “tmclure@springfield.com”, gender: “MALE”}
Looking at the output from the logging adapter, you can see the two messages that were sent to the “outboundChannel” due to the logging channel adapter and you can see that they were both in JSON format.
Conclusion
This configuration is barely the tip of the iceberg when it comes to Spring Integration, but it illustrates just how simple Spring Integration can make orchestrating complex process flows or integrating with internal and external systems, while keeping each piece of functionality logically decoupled. The result is maintainable, testable, and allows the developer to focus on their core business logic. If you have integration needs, using Spring and Spring Integration provides a module for your particular integration, so definitely consider it.
List of Spring Integration Modules:
AMQP
RSS Feed
File
FTP
Gemfire
HTTP
IP
JDBC
JMS
JMX
JPA
Mail
MongoDB
MQTT
Redis
RMI
SFTP
Stream
Twitter
Web Services
XMPP
Community Modules:
Amazon Web Services (AWS) Support
Kafka Support
MQ Telemetry Transport (MQTT) Support
Print Support
SMB Support
SMPP Support
Splunk Support
Voldemort Support
XQuery Support
References: http://spring.io
The post Spring Integration: The Tip of the Iceberg appeared first on blog.credera.com.