Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

28/10/2020 Spring Integration Java DSL | Baeldung

(/)

Spring Integration Java DSL


Last modi ed: February 12, 2020

by Dhawal Kapil (https://www.baeldung.com/author/dhawal-kapil/)

Spring (https://www.baeldung.com/category/spring/) +
Spring Integration (https://www.baeldung.com/tag/spring-integration/)

I just announced the new Learn Spring course, focused on


the fundamentals of Spring 5 and Spring Boot 2:
>> CHECK OUT THE COURSE (/ls-course-start)

1. Introduction 
In this tutorial, we'll learn about the Spring Integration Java DSL for creating
application integrations.
We'll take the le-moving integration we built in Introduction to Spring
Integration (/spring-integration) and use the DSL instead.

2. Dependencies

https://www.baeldung.com/spring-integration-java-dsl 1/11
28/10/2020 Spring Integration Java DSL | Baeldung

The Spring Integration Java DSL is part of Spring Integration Core


(https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.sprin
gframework.integration%22%20AND%20a%3A%22spring-integration-core%22).
So, we can add that dependency:
1 <dependency>
2 <groupId>org.springframework.integration</groupId>
3 <artifactId>spring-integration-core</artifactId>
4 <version>5.0.6.RELEASE</version>
5 </dependency>

And to work on our le-moving application, we'll also need Spring Integration


File
(https://search.maven.org/classic/#search%7Cgav%7C1%7Ca%3A%22spring-
integration- le%22):
1 <dependency>
2 <groupId>org.springframework.integration</groupId>
3 <artifactId>spring-integration-file</artifactId>
4 <version>5.0.6.RELEASE</version>
5 </dependency>

3. Spring Integration Java DSL


Before the Java DSL, users would con gure Spring Integration components in
XML.
The DSL introduces some uent builders from which we can easily create a
complete a Spring Integration pipeline purely in Java. 
So, let's say we wanted to create a channel that uppercases any data coming
through the pipe.
In the past, we might have done:
1 <int:channel id="input"/>
2
<int:transformer input-channel="input"
3
expression="payload.toUpperCase()" />

And now we can instead do:

https://www.baeldung.com/spring-integration-java-dsl 2/11
28/10/2020 Spring Integration Java DSL | Baeldung

1 @Bean
2 public IntegrationFlow upcaseFlow() {
3 return IntegrationFlows.from("input")
4 .transform(String::toUpperCase)
5 .get();
6 }

4. The File-Moving App


To begin our le-moving integration, we'll need some simple building blocks.

4.1. Integration Flow


The rst building block we need is an integration ow, which we can get from
the IntegrationFlows builder:
1 IntegrationFlows.from(...)

from can take several types, but in this tutorial, we will look at just three:
MessageSources
MessageChannels, and
Strings
We'll talk about all three shortly.
After we have called from, some customization methods are now available to
us:
1 IntegrationFlow flow = IntegrationFlows.from(sourceDirectory())
2 .filter(onlyJpgs())
3 .handle(targetDirectory())
4 // add more components
5 .get();

Ultimately, IntegrationFlows will always produce an instance


of IntegrationFlow, which is the nal product of any Spring Integration app.
This pattern of taking input, performing the appropriate transformations,
and emitting the results is fundamental to all Spring Integration apps.

https://www.baeldung.com/spring-integration-java-dsl 3/11
28/10/2020 Spring Integration Java DSL | Baeldung

4.2. Describing an Input Source


First, to move les, we'll need to indicate to our integration ow where it
should look for them, and for that, we need a MessageSource:
1 @Bean
2 public MessageSource<File> sourceDirectory() {
3 // .. create a message source
4 }

Simply put, a MessageSource is a place from which messages can come that
are external to the application
(http://joshlong.com/jl/blogPost/spring_integration_adapters_gateways_and
_channels.html).
More speci cally, we need something that can adapt that external source into
the Spring messaging representation. And since this adaptation is focused
on input, these are often called Input Channel Adapters.
The spring-integration- le dependency gives us an input channel adapter
that's great for our use case: FileReadingMessageSource:
1 @Bean
2 public MessageSource<File> sourceDirectory() {
FileReadingMessageSource messageSource = new
3
FileReadingMessageSource();
4 messageSource.setDirectory(new File(INPUT_DIR));
5 return messageSource;
6 }

Here, our FileReadingMessageSource will be reading a directory given by


INPUT_DIR and will create a MessageSource from it.
Let's specify this as our source in an IntegrationFlows.from invocation:
1 IntegrationFlows.from(sourceDirectory());

4.3. Con guring an Input Source


Now, if we are thinking about this as a long-lived application, we'll probably
want to be able to notice les as they come in, not just move the les that
are already there at startup.

https://www.baeldung.com/spring-integration-java-dsl 4/11
28/10/2020 Spring Integration Java DSL | Baeldung

To facilitate this, from can also take extra con gurers as further customization


of the input source:
IntegrationFlows.from(sourceDirectory(), configurer ->
1
configurer.poller(Pollers.fixedDelay(10000)));

In this case, we can make our input source more resilient by telling Spring
Integration to poll that source–our lesystem in this case–every 10 seconds.
And, of course, this doesn't apply to just our le input source, we could add
this poller to any MessageSource.

4.4. Filtering Messages from an Input Source


Next, let's suppose we want our le-moving application to move speci c les
only, say image les having jpg extension.
For this, we can use GenericSelector:
1 @Bean
2 public GenericSelector<File> onlyJpgs() {
3 return new GenericSelector<File>() {
4
5 @Override
6 public boolean accept(File source) {
7 return source.getName().endsWith(".jpg");
8 }
9 };
10 }

So, let's update our integration ow again:


1 IntegrationFlows.from(sourceDirectory())
2 .filter(onlyJpgs());

Or, because this lter is so simple, we could have instead de ned it using a
lambda:
1 IntegrationFlows.from(sourceDirectory())
2 .filter(source -> ((File) source).getName().endsWith(".jpg"));

4.5. Handling Messages With Service Activators


https://www.baeldung.com/spring-integration-java-dsl 5/11
28/10/2020 Spring Integration Java DSL | Baeldung

Now that we have a ltered list of les, we need to write them to a new
location.
Service Activators are what we turn to when we're thinking about outputs in
Spring Integration.
Let's use the FileWritingMessageHandler service activator from spring-
integration- le:
1 @Bean
2 public MessageHandler targetDirectory() {
FileWritingMessageHandler handler = new
3
FileWritingMessageHandler(new File(OUTPUT_DIR));
4 handler.setFileExistsMode(FileExistsMode.REPLACE);
5 handler.setExpectReply(false);
6 return handler;
7 }

Here, our FileWritingMessageHandler will write each Message payload it


receives to OUTPUT_DIR.
Again, let's update:
1 IntegrationFlows.from(sourceDirectory())
2 .filter(onlyJpgs())
3 .handle(targetDirectory());

And notice, by the way, the usage of setExpectReply. Because integration


ows can be bidirectional, this invocation indicates that this particular pipe is
one way.

4.6. Activating Our Integration Flow


When we have added all our components we need to register our
IntegrationFlow as a bean to activate it:
1 @Bean
2 public IntegrationFlow fileMover() {
return IntegrationFlows.from(sourceDirectory(), c ->
3
c.poller(Pollers.fixedDelay(10000)))
4 .filter(onlyJpgs())
5 .handle(targetDirectory())
6 .get();
7 }

https://www.baeldung.com/spring-integration-java-dsl 6/11
28/10/2020 Spring Integration Java DSL | Baeldung

The get method extracts an IntegrationFlow instance that we need to register


as a Spring Bean.
As soon as our application context loads, all our components contained in our
IntegrationFlow gets activated.
And now, our application will start moving les from the source directory to
target directory.

5. Additional Components
In our DSL-based le-moving application, we created an Inbound Channel
Adapter, a Message Filter, and a Service Activator.
Let's look at a few other common Spring Integration components and see how
we might use them.

5.1. Message Channels


As mentioned earlier, a Message Channel is another way to initialize a ow:
1 IntegrationFlows.from("anyChannel")

We can read this as “please nd or create a channel bean called anyChannel.


Then, read any data that is fed into anyChannel from other ows.”
But, really it is more general-purpose than that.
Simply put, a channel abstracts away producers from consumers, and we can
think of it as a Java Queue. A channel can be inserted at any point in the
ow.
Let's say, for example, that we want to prioritize the les as they get moved
from one directory to the next:
1 @Bean
2 public PriorityChannel alphabetically() {
3 return new PriorityChannel(1000, (left, right) ->
4 ((File)left.getPayload()).getName().compareTo(
5 ((File)right.getPayload()).getName()));
6 }

https://www.baeldung.com/spring-integration-java-dsl 7/11
28/10/2020 Spring Integration Java DSL | Baeldung

Then, we can insert an invocation to channel in between our ow:


1 @Bean
2 public IntegrationFlow fileMover() {
3 return IntegrationFlows.from(sourceDirectory())
4 .filter(onlyJpgs())
5 .channel("alphabetically")
6 .handle(targetDirectory())
7 .get();
8 }

There are dozens of channels to pick from, some of the more handy ones
being for concurrency, auditing, or intermediate persistence (think Kafka or
JMS bu ers).
Also, channels can be powerful when combined with Bridges.

5.2. Bridge
When we want to combine two channels, we use a Bridge.
Let's imagine that instead of writing directly to an output directory, we instead
had our le-moving app write to another channel:
1 @Bean
2 public IntegrationFlow fileReader() {
3 return IntegrationFlows.from(sourceDirectory())
4 .filter(onlyJpgs())
5 .channel("holdingTank")
6 .get();
7 }

Now, because we've simply written it to a channel, we can bridge from there
to other ows.
Let's create a bridge that polls our holding tank for messages and writes them
to a destination:

https://www.baeldung.com/spring-integration-java-dsl 8/11
28/10/2020 Spring Integration Java DSL | Baeldung

1 @Bean
2 public IntegrationFlow fileWriter() {
3 return IntegrationFlows.from("holdingTank")
.bridge(e -> e.poller(Pollers.fixedRate(1, TimeUnit.SECONDS,
4
20)))
5 .handle(targetDirectory())
6 .get();
7 }

Again, because we wrote to an intermediate channel, now we can add another


ow that takes these same les and writes them at a di erent rate:
1 @Bean
2 public IntegrationFlow anotherFileWriter() {
3 return IntegrationFlows.from("holdingTank")
.bridge(e -> e.poller(Pollers.fixedRate(2, TimeUnit.SECONDS,
4
10)))
5 .handle(anotherTargetDirectory())
6 .get();
7 }

As we can see, individual bridges can control the polling con guration for
di erent handlers.
As soon as our application context is loaded, we now have a more complex
app in action that will start moving les from the source directory to two target
directories.

6. Conclusion
In this article, we saw various ways to use the Spring Integration Java DSL to
build di erent integration pipelines.
Essentially, we were able to recreate the le-moving application from a
previous tutorial, this time using pure java.
Also, we took a look at a few other components like channels and bridges.
The complete source code used in this tutorial is available over on Github
(https://github.com/eugenp/tutorials/tree/master/spring-integration).

https://www.baeldung.com/spring-integration-java-dsl 9/11
28/10/2020 Spring Integration Java DSL | Baeldung

I just announced the new Learn Spring course,


focused on the fundamentals of Spring 5 and Spring
Boot 2:
>> CHECK OUT THE COURSE (/ls-course-end)

Comments are closed on this article!

CATEGORIES
SPRING (HTTPS://WWW.BAELDUNG.COM/CATEGORY/SPRING/)
REST (HTTPS://WWW.BAELDUNG.COM/CATEGORY/REST/)
JAVA (HTTPS://WWW.BAELDUNG.COM/CATEGORY/JAVA/)
SECURITY (HTTPS://WWW.BAELDUNG.COM/CATEGORY/SECURITY-2/)
PERSISTENCE (HTTPS://WWW.BAELDUNG.COM/CATEGORY/PERSISTENCE/)
JACKSON (HTTPS://WWW.BAELDUNG.COM/CATEGORY/JSON/JACKSON/)
HTTP CLIENT-SIDE (HTTPS://WWW.BAELDUNG.COM/CATEGORY/HTTP/)
KOTLIN (HTTPS://WWW.BAELDUNG.COM/CATEGORY/KOTLIN/)

SERIES
JAVA “BACK TO BASICS” TUTORIAL (/JAVA-TUTORIAL)
JACKSON JSON TUTORIAL (/JACKSON)
HTTPCLIENT 4 TUTORIAL (/HTTPCLIENT-GUIDE)
REST WITH SPRING TUTORIAL (/REST-WITH-SPRING-SERIES)
SPRING PERSISTENCE TUTORIAL (/PERSISTENCE-WITH-SPRING-SERIES)
SECURITY WITH SPRING (/SECURITY-SPRING)

ABOUT
ABOUT BAELDUNG (/ABOUT)

https://www.baeldung.com/spring-integration-java-dsl 10/11
28/10/2020 Spring Integration Java DSL | Baeldung

THE COURSES (HTTPS://COURSES.BAELDUNG.COM)


JOBS (/TAG/ACTIVE-JOB/)
THE FULL ARCHIVE (/FULL_ARCHIVE)
EDITORS (/EDITORS)
OUR PARTNERS (/PARTNERS)
ADVERTISE ON BAELDUNG (/ADVERTISE)

TERMS OF SERVICE (/TERMS-OF-SERVICE)


PRIVACY POLICY (/PRIVACY-POLICY)
COMPANY INFO (/BAELDUNG-COMPANY-INFO)
CONTACT (/CONTACT)

https://www.baeldung.com/spring-integration-java-dsl 11/11

You might also like