GH-3946: Revise Router channelKeyFallback option (#3948)

* GH-3946: Revise Router channelKeyFallback option

Fixes https://github.com/spring-projects/spring-integration/issues/3946

The `AbstractMappingMessageRouter` has both `resolutionRequired` and `channelKeyFallback`
as `true` by default.
End-users expects them to back off when they set a `defaultOutputChannel`.
They really want something similar to Java `switch` statement

* Change the logic in the `AbstractMappingMessageRouter` to reset `channelKeyFallback`
to `false` when `defaultOutputChannel` to avoid attempts to resolve channel from name,
but rather fallback to `defaultOutputChannel` as it states from th mentioned
Java `switch` statement experience
* Deprecate `RouterSpec.noChannelKeyFallback()` in favor of newly introduced `channelKeyFallback(boolean)`
* Call `channelKeyFallback(false)` from an overloaded `defaultOutputToParentFlow()`
to reflect the mentioned expected behavior in Java DSL as well.
* Respectively, deprecate `KotlinRouterSpec.noChannelKeyFallback()` wrapper
in favor of newly introduced `channelKeyFallback(channelKeyFallback: Boolean)`
* Remove redundant already `noChannelKeyFallback()` option in the `NoFallbackAllowedTests`
* Document the change and new behavior

* Fix `IntegrationGraphServerTests` to `setChannelKeyFallback(true)` explicitly

* Remove not relevant `default-output-channel` from the `DynamicRouterTests-context.xml`

* Reject an `AbstractMappingMessageRouter` configuration where `defaultOutputChannel` is provided
and both `channelKeyFallback` & `resolutionRequired` are set to `true`.
Such a state makes `defaultOutputChannel` as not reachable and may cause some confusions in target
applications.

* Remove `&` symbol from JavaDocs

* Fix `boolean` expression for `AbstractMappingMessageRouter` configuration check

* Fix `IntegrationGraphServerTests` for new router behavior

* Improve language in docs
This commit is contained in:
Artem Bilan
2022-11-16 14:19:26 -05:00
committed by GitHub
parent 60ba5444e7
commit e9257958fe
8 changed files with 139 additions and 28 deletions

View File

@@ -33,6 +33,8 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Gary Russell
* @author Artem Bilan
*
* @since 5.2
*
*/
@@ -53,9 +55,7 @@ public class NoFallbackAllowedTests {
@Bean
public IntegrationFlow flow() {
return f -> f.route("headers.whereTo", r -> r
.noChannelKeyFallback()
.defaultOutputChannel(queue()));
return f -> f.route("headers.whereTo", r -> r.defaultOutputChannel(queue()));
}
@Bean

View File

@@ -135,7 +135,7 @@ public class IntegrationGraphServerTests {
List<Map<?, ?>> links = (List<Map<?, ?>>) map.get("links");
assertThat(links).isNotNull();
assertThat(links.size()).isEqualTo(34);
assertThat(links.size()).isEqualTo(32);
jsonArray =
JsonPathUtils.evaluate(baos.toByteArray(), "$..nodes[?(@.name == 'expressionRouter.router')]");
@@ -169,7 +169,7 @@ public class IntegrationGraphServerTests {
assertThat(nodes.size()).isEqualTo(34);
links = (List<Map<?, ?>>) map.get("links");
assertThat(links).isNotNull();
assertThat(links.size()).isEqualTo(37);
assertThat(links.size()).isEqualTo(35);
jsonArray = JsonPathUtils.evaluate(baos.toByteArray(), "$..nodes[?(@.name == 'router.router')]");
routerJson = jsonArray.toJSONString();
@@ -347,7 +347,7 @@ public class IntegrationGraphServerTests {
HeaderValueRouter router = new HeaderValueRouter("foo");
router.setChannelMapping("bar", "barChannel");
router.setChannelMapping("baz", "bazChannel");
router.setDefaultOutputChannel(discards());
router.setChannelKeyFallback(true);
return router;
}
@@ -365,7 +365,7 @@ public class IntegrationGraphServerTests {
public ExpressionEvaluatingRouter expressionRouter() {
ExpressionEvaluatingRouter router = new ExpressionEvaluatingRouter(
new SpelExpressionParser().parseExpression("headers['foo']"));
router.setDefaultOutputChannel(discards());
router.setChannelKeyFallback(true);
return router;
}
@@ -404,7 +404,7 @@ public class IntegrationGraphServerTests {
@Bean
@InboundChannelAdapter(channel = "fizChannel", autoStartup = "false")
public MessageSource<String> testSource() {
return new AbstractMessageSource<String>() {
return new AbstractMessageSource<>() {
@Override
public String getComponentType() {