Let's imagine a simple flow:
Modelling it is not that difficult. Here's our MessageRouter class:
And finally persister: We can see it in action by running the following class:
Everything seems fine here, but we have a problem - tight coupling.
Message router knows about handlers and handlers know about persister.
We would gain loose coupling and high cohesion if they weren't aware of each other which would automatically make them concentrate on one task only.
Spring Integration can help us achieve this.
It is a separate module of Spring, enabling lightweight messaging within application and supporting Enterprise Integration Patterns.
All the arrows from the above picture will be represented as channels.
The XML Spring context configuration for the channels looks pretty straightforward:
Actually it's not even required as Spring can create them by default.
Apart from the channels, our MessageRouter only role is to return the channel name to which the message will be passed.
Also the handlers and persister need to become Service Activators (their methods will be invoked when the message will go through the channel).
The config for those:
To see it in action we can run the following class:
Notice that the code is concise and simple.
The components do not depend on each other.
What is more, if we wanted to modify the flow and move Persister component in front of the MessageRouter, we would need to change the xml config to:
Changing the flow in the first version that is using plain Java code would require much more modifications.
Nevertheless we increased the complexity of our application. Now we depend on a framework and we need to maintain additional configuration in an XML file.
Another big disadvantage is testing. We could easily unit test the previous code using mocks. Now we need to test the Java code and Spring Integration configuration as well, which is not that simple.
I'll show how to do it in the next post.