GH-2765: Add discardChannel for splitter (#2883)
* GH-2765: Add discardChannel for splitter Fixes https://github.com/spring-projects/spring-integration/issues/2765 When encountering empty collections, splitter should be able to send the result to a discard channel. Currently, when encountering an empty collection, the splitter ends the flow. Some use-cases may rely on a custom split function which may returns empty collections. These use-cases should be able to define a discard channel so they can proceed with a possible compensation flow. * Add `discardChannel` option to the `AbstractMessageSplitter` * Delegate `discardChannel` population from everywhere it is possible: DSL, XML, `AbstractMessageSplitter` extension like `FileSplitter` etc. * Fix `FileSplitterTests` for broken charset * Document new feature; fix some typos and out-dated code sample * * Fix `SplitterFactoryBean` for NPE on the `discardChannelName` propagation * * Check `this.discardChannel` first * `Assert.state()` in `doInit()` for mutual exclusiveness
This commit is contained in:
committed by
Gary Russell
parent
7fa1161f5b
commit
818be4cbe8
@@ -455,15 +455,13 @@ The following example shows how to use the `split()` method by providing a lambd
|
||||
@Bean
|
||||
public IntegrationFlow splitFlow() {
|
||||
return IntegrationFlows.from("splitInput")
|
||||
.split(s ->
|
||||
s.applySequence(false).get().getT2().setDelimiters(","))
|
||||
.channel(MessageChannels.executor(this.taskExecutor()))
|
||||
.split(s -> s.applySequence(false).delimiters(","))
|
||||
.channel(MessageChannels.executor(taskExecutor()))
|
||||
.get();
|
||||
}
|
||||
----
|
||||
|
||||
The preceding example creates a splitter that splits a message containing a comma-delimited `String`.
|
||||
Note: The `getT2()` method comes from a `Tuple` `Collection`, which is the result of `EndpointSpec.get()`, and represents a pair of `ConsumerEndpointFactoryBean` and `DefaultMessageSplitter` for the preceding example.
|
||||
|
||||
Also see <<java-dsl-class-cast>>.
|
||||
|
||||
@@ -1157,7 +1155,7 @@ Otherwise, creating such a configuration by using `IntegrationFlow` does not mak
|
||||
By default a `GatewayProxyFactoryBean` gets a conventional bean name, such as `[FLOW_BEAN_NAME.gateway]`.
|
||||
You can change that ID by using the `@MessagingGateway.name()` attribute or the overloaded `from(Class<?> serviceInterface, String beanName)` factory method.
|
||||
|
||||
With Java 8, you can even create an integration fateway with the `java.util.function` interfaces, as the following example shows:
|
||||
With Java 8, you can even create an integration gateway with the `java.util.function` interfaces, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
|
||||
@@ -64,6 +64,10 @@ In this case, the target `Iterator` is built on their iteration functionality.
|
||||
|
||||
In addition, if the splitter's output channel is an instance of a `ReactiveStreamsSubscribableChannel`, the `AbstractMessageSplitter` produces a `Flux` result instead of an `Iterator`, and the output channel is subscribed to this `Flux` for back-pressure-based splitting on downstream flow demand.
|
||||
|
||||
Starting with version 5.2, the splitter supports a `discardChannel` option for sending those request messages for which a split function has returned an empty container (collection, array, stream, `Flux` etc.).
|
||||
In this case there is just no item to iterate for sending to the `outputChannel`.
|
||||
The `null` splitting result remains as an end of flow indicator.
|
||||
|
||||
==== Configuring a Splitter with XML
|
||||
|
||||
A splitter can be configured through XML as follows:
|
||||
@@ -73,11 +77,12 @@ A splitter can be configured through XML as follows:
|
||||
----
|
||||
<int:channel id="inputChannel"/>
|
||||
|
||||
<int:splitter id="splitter" <1>
|
||||
ref="splitterBean" <2>
|
||||
method="split" <3>
|
||||
input-channel="inputChannel" <4>
|
||||
output-channel="outputChannel" /> <5>
|
||||
<int:splitter id="splitter" <1>
|
||||
ref="splitterBean" <2>
|
||||
method="split" <3>
|
||||
input-channel="inputChannel" <4>
|
||||
output-channel="outputChannel" <5>
|
||||
discard-channel="discardChannel" /> <6>
|
||||
|
||||
<int:channel id="outputChannel"/>
|
||||
|
||||
@@ -94,6 +99,8 @@ Optional.
|
||||
Required.
|
||||
<5> The channel to which the splitter sends the results of splitting the incoming message.
|
||||
Optional (because incoming messages can specify a reply channel themselves).
|
||||
<6> The channel to which the request message is sent in case of empty splitting result.
|
||||
Optional (the will stop as in case of `null` result).
|
||||
====
|
||||
|
||||
We recommend using a `ref` attribute if the custom splitter implementation can be referenced in other `<splitter>` definitions.
|
||||
|
||||
@@ -19,6 +19,9 @@ See <<rate-limiter-advice>> for more information.
|
||||
The `JsonToObjectTransformer` now supports generics for the target object to deserialize into.
|
||||
See <<json-transformers>> for more information.
|
||||
|
||||
RThe `splitter` now supports a `discardChannel` configuration option.
|
||||
See <<splitter>> for more information.
|
||||
|
||||
[[x5.2-amqp]]
|
||||
==== AMQP Changes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user