Monday, May 5, 2014

Spring Integration 4.0: A complete XML-free example

1   Introduction


Spring Integration 4.0 is finally here, and this release comes with very nice features. The one covered in this article is the possibility to configure an integration flow without using XML at all. Those people that don’t like XML will be able to develop an integration application with just using JavaConfig.

This article is divided in the following sections:
  1. Introduction.
  2. An overview of the flow.
  3. Spring configuration.
  4. Detail of the endpoints.
  5. Testing the entire flow.
  6. Conclusion.

The source code can be found at github.

The source code of the web service invoked in this example can be found at the spring-samples repository at github.


2   An overview of the flow


The example application shows how to configure several messaging and integration endpoints. The user asks for a course by specifying the course Id. The flow will invoke a web service and return the response to the user. Additionally, some type of courses will be stored to a database. 

The flow is as follows:
  • An integration gateway (course service) serves as the entry to the messaging system.
  • A transformer builds the request message from the user specified course Id.
  • A web service outbound gateway sends the request to a web service and waits for a response.
  • A service activator is subscribed to the response channel in order to return the course name to the user.
  • A filter is also subscribed to the response channel. This filter will send some types of courses to a mongodb channel adapter in order to store the response to a database.

The following diagram better shows how the flow is structured:




3   Spring configuration


As discussed in the introduction section, the entire configuration is defined with JavaConfig. This configuration is split into three files: infrastructure, web service and database configuration. Let’s check it out:

3.1   Infrastructure configuration


This configuration file only contains the definition of message channels. The messaging endpoints (transformer, filter, etc...) are configured with annotations.

InfrastructureConfiguration.java
The @ComponentScan annotation searches for @Component annotated classes, which are our defined messaging endpoints; the filter, the transformer and the service activator.

The @IntegrationComponentScan annotation searches for specific integration annotations. In our example, it will scan the entry gateway which is annotated with @MessagingGateway.

The @EnableIntegration annotation enables integration configuration. For example, method level annotations like @Transformer or @Filter.

3.2   Web service configuration


This configuration file configures the web service outbound gateway and its required marshaller.

WebServiceConfiguration.java
The gateway allows us to define its output channel but not the input channel. We need to annotate the adapter with @ServiceActivator in order to subscribe it to the invocation channel and avoid having to autowire it in the message channel bean definition.

3.3   Database configuration


This configuration file defines all necessary beans to set up mongoDB. It also defines the mongoDB outbound channel adapter.

MongoDBConfiguration.java
Like the web service gateway, we can’t set the input channel to the adapter. I also have done that by specifying the input channel in the @ServiceActivator annotation.


4   Detail of the endpoints


The first endpoint of the flow is the integration gateway, which will put the argument (courseId) into the payload of a message and send it to the request channel.

The message containing the course id will reach the transformer. This endpoint will build the request object that the web service is expecting:

Subscribed to the response channel, which is the channel where the web service reply will be sent, there’s a service activator that will receive the response message and deliver the course name to the client:

Also subscribed to the response channel, a filter will decide based on its type, if the course is required to be stored to a database:


5   Testing the entire flow


The following client will send two requests; a BC type course request that will be stored to the database and a DF type course that will be finally filtered:

This will result in the following console output:

CourseRequestBuilder|Building request for course [BC-45]
CourseResponseHandler|Course with ID [BC-45] received: Introduction to Java
StoredCoursesFilter|Course [BC-45] validated. Storing to database
CourseRequestBuilder|Building request for course [DF-21]
CourseResponseHandler|Course with ID [DF-21] received: Functional Programming Principles in Scala
StoredCoursesFilter|Course [DF-21] filtered. Not a BF course



6   Conclusion


We have learnt how to set up and test an application powered with Spring Integration using no XML configuration. Stay tuned, because Spring Integration Java DSL with Spring Integration extensions is on its way!

I'm publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.