For the latest stable version, please use Spring Integration 6.3.2! |
Integration Flows Composition
With the MessageChannel
abstraction as a first class citizen in Spring Integration, the composition of integration flows was always assumed.
The input channel of any endpoint in the flow can be used to send messages from any other endpoint and not only from the one which has this channel as an output.
Furthermore, with a @MessagingGateway
contract, Content Enricher components, composite endpoints like a <chain>
, and now with IntegrationFlow
beans (e.g. IntegrationFlowAdapter
), it is straightforward enough to distribute the business logic between shorter, reusable parts.
All that is needed for the final composition is knowledge about a MessageChannel
to send to or receive from.
Starting with version 5.5.4
, to abstract more from MessageChannel
and hide implementation details from the end-user, the IntegrationFlow
introduces the from(IntegrationFlow)
factory method to allow starting the current IntegrationFlow
from the output of an existing flow:
@Bean
IntegrationFlow templateSourceFlow() {
return IntegrationFlow.fromSupplier(() -> "test data")
.channel("sourceChannel")
.get();
}
@Bean
IntegrationFlow compositionMainFlow(IntegrationFlow templateSourceFlow) {
return IntegrationFlow.from(templateSourceFlow)
.<String, String>transform(String::toUpperCase)
.channel(c -> c.queue("compositionMainFlowResult"))
.get();
}
On the other hand, the IntegrationFlowDefinition
has added a to(IntegrationFlow)
terminal operator to continue the current flow at the input channel of some other flow:
@Bean
IntegrationFlow mainFlow(IntegrationFlow otherFlow) {
return f -> f
.<String, String>transform(String::toUpperCase)
.to(otherFlow);
}
@Bean
IntegrationFlow otherFlow() {
return f -> f
.<String, String>transform(p -> p + " from other flow")
.channel(c -> c.queue("otherFlowResultChannel"));
}
The composition in the middle of the flow is simply achievable with an existing gateway(IntegrationFlow)
EIP-method.
This way we can build flows with any complexity by composing them from simpler, reusable logical blocks.
For example, you may add a library of IntegrationFlow
beans as a dependency, and it is just enough to have their configuration classes imported to the final project and autowired for your IntegrationFlow
definitions.