Spring Integration Custom Transformer Example
1. Introduction
Spring Integration provides a transformer mechanism to convert message payloads from one form to another between two channels. In this article, we will see how to implement a simple custom transformer.
2. Application
The application is a Spring Boot application in which a Map
is sent to a message channel. A Spring Integration Transformer
listens to the message channel, transforms the Map
to a Ticket
object and sends it to an output channel. Finally, the message is printed to stdout.
3. Environment
I have used the following technologies for this application:
- Java 1.8
- Spring Boot 1.5.10
- Maven 3.3.9
- Ubuntu 16.04 LTS
4. Source Code
This is a Maven-based project, so all the required libraries are declared in pom.xml
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.javacodegeeks.springintegration.transformer</groupId> <artifactId>simpletransformer</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>simpletransformer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Below is the domain object of the application. It has two fields ticketId
and description
, both of type String
.
Ticket.java
package org.javacodegeeks.springintegration.transformer.simpletransformer.domain; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; @Getter @Setter @NoArgsConstructor @ToString public class Ticket { private String ticketId; private String description; }
Also, the lombok
annotations @Getter
, @Setter
, @NoArgsConstructor
and @ToString
are used to generate the getters and setters, the default constructor and the toString
method.
In the below file, two channels “input” and “output” are configured, which get the DefaultChannel
type.
transformer-context.xml
<?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:context="http://www.springframework.org/schema/context" xmlns:int="http://www.springframework.org/schema/integration" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd"> <context:component-scan base-package="org.javacodegeeks.springintegration.transformer.simpletransformer" /> <int:transformer input-channel="input" output-channel="output" ref="mapToObject" /> <int:channel id="input" /> <int:channel id="output"> <int:queue /> </int:channel> </beans>
We also configure a Spring Integration transformer which listens to input channel and writes to the output channel using the MapToObject
class to transform the input to output.
The below class is the custom transformer that we use in the application.
MapToObject.java
package org.javacodegeeks.springintegration.transformer.simpletransformer.util; import java.util.Map; import org.javacodegeeks.springintegration.transformer.simpletransformer.domain.Ticket; import org.springframework.stereotype.Component; @Component public class MapToObject { public Ticket map(Map message) { Ticket ticket = new Ticket(); ticket.setTicketId(message.get("ticketId")); ticket.setDescription(message.get("description")); return ticket; } }
This class is annotated with @Component
so that it is available for the Spring run time during classpath scanning to create beans . The map
method takes a Java Map
object as input parameter. It constructs a Ticket
object and sets the values of its properties to the values from the input map. The method returns the Ticket
object.
Below, is the main class of the application.
SimpleTransformerApplication.java
package org.javacodegeeks.springintegration.transformer.simpletransformer; import java.util.HashMap; import java.util.Map; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.PollableChannel; @SpringBootApplication public class SimpletransformerApplication { public static void main(String[] args) { SpringApplication.run(SimpletransformerApplication.class, args); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("transformer-context.xml"); MessageChannel input = context.getBean("input", MessageChannel.class); PollableChannel output = context.getBean("output", PollableChannel.class); Map ticketMap = new HashMap(); ticketMap.put("ticketId", "1001"); ticketMap.put("description", "First ticket"); System.out.println("Sent: " + ticketMap); input.send(MessageBuilder.withPayload(ticketMap).build()); System.out.println("received " + output.receive().getPayload()); context.close(); } }
From the configuration, it gets two beans: input of type MessageChannel
and output of type PollableChannel
. It then creates a Java HashMap
object called ticketMap
and sets the value for two keys, ticketId
and description
. The ticketMap
is sent to the input channel. Behind the scene, the transformer object converts it to a Ticket
object and writes it to the output channel. The method then invokes receive
on the output channel, gets the object and writes it to stdout.
5. How To Run
At the command prompt, just run
$ mvn spring-boot:run.
You will see the following output:
Sent: {description=First ticket, ticketId=1001} received Ticket(ticketId=1001, description=First ticket)
6. Conclusion
In this article, we have seen a simple custom transformer functionality that takes in a Java Map
object and outputs a custom domain object. Spring Integration provides several built-in transformers for transformation: object-to-string
, object-to-map-transformer
, map-to-object transformer
, json-to-object-transformer
, object-to-json-transformer
and so on. In the map
method, we could transform the input object to any other form, say csv or pdf.
7. Download the Source Code
You can download the full source code of this example here: simpletransformer.zip