Introduce high-level API for flows composition (#3624)

* Introduce high-level API for flows composition

For better end-user experience and more smooth integration logic
decomposition and distribution introduce an `IntegrationFlows.from(IntegrationFlow)`
to let to start the current flow from existing one.
On the other hand introduce an `BaseIntegrationFlowDefinition.to(IntegrationFlow)`
to let to continue the flow logic in the other existing one.
This way we can extract some templating logic into separate `IntegrationFlow` definitions
allowing at the same time to decompose a complex flow definition into logical reusable parts

* * Add more tests

* * Fix Checkstyle violation
* Add `@SuppressWarnings("overloads")` to new `from(IntegrationFlow)` and existing `from(Publisher)`.
Technically it does not make sense since `PublisherIntegrationFlow` is not a `public` class

* * Add docs
* Fix language in JavaDocs according review

* Fix language in the docs after review

Co-authored-by: Gary Russell <grussell@vmware.com>

Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
Artem Bilan
2021-09-08 17:14:29 -04:00
committed by GitHub
parent b8785e5f9c
commit 4456caffa1
10 changed files with 379 additions and 4 deletions

View File

@@ -1378,3 +1378,58 @@ public IntegrationFlow customFlowDefinition() {
}
----
====
[[integration-flows-composition]]
=== 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 `IntegrationFlows` introduces the `from(IntegrationFlow)` factory method to allow starting the current `IntegrationFlow` from the output of an existing flow:
====
[source,java]
----
@Bean
IntegrationFlow templateSourceFlow() {
return IntegrationFlows.fromSupplier(() -> "test data")
.channel("sourceChannel")
.get();
}
@Bean
IntegrationFlow compositionMainFlow(IntegrationFlow templateSourceFlow) {
return IntegrationFlows.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:
====
[source,java]
----
@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.

View File

@@ -47,6 +47,13 @@ See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
The `MessageGroup` abstraction can be supplied with a `condition` to evaluate later on to make a decision for the group.
See <<./message-store.adoc#message-group-condition,Message Group Condition>> for more information.
[[x5.5-integration-flows-composition]]
==== Integration Flows Composition
The new `IntegrationFlows.from(IntegrationFlow)` factory method has been added to allow starting the current `IntegrationFlow` from the output of an existing flow.
In addition, the `IntegrationFlowDefinition` has added a `to(IntegrationFlow)` terminal operator to continue the current flow at the input channel of some other flow.
See <<./dsl.adoc#integration-flows-composition,Integration Flows Composition>> for more information.
[[x5.5-amqp]]
==== AMQP Changes