JavaConfig/DSL Docs for Routers (Part 1)
Also fix DSL messing `sendTimeout` property for routers. Since other message handlers have this property on the `ConsumerEndpointSpec`, add support there instead of `RouterSpec`, for consistency. Also fix `ConsumerEndpointSpec` `sendTimeout` - can be applied to any `AbstractMessageProducingHandler`, not just `AbstractReplyProducingMessageHandler`. Ditto for `async`. Polishing
This commit is contained in:
committed by
Artem Bilan
parent
c85b9cbb20
commit
70652739b8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,6 +37,7 @@ import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.integration.context.IntegrationObjectSupport;
|
||||
import org.springframework.integration.context.Orderable;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.integration.handler.AbstractMessageProducingHandler;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.support.context.NamedComponent;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -224,8 +225,8 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageH
|
||||
}
|
||||
}
|
||||
if (this.async != null) {
|
||||
if (actualHandler instanceof AbstractReplyProducingMessageHandler) {
|
||||
((AbstractReplyProducingMessageHandler) actualHandler)
|
||||
if (actualHandler instanceof AbstractMessageProducingHandler) {
|
||||
((AbstractMessageProducingHandler) actualHandler)
|
||||
.setAsync(this.async);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,9 @@ import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.handler.AbstractMessageProducingHandler;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.router.AbstractMessageRouter;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.integration.transaction.TransactionInterceptorBuilder;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
@@ -39,6 +41,7 @@ import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
* @param <H> the target {@link MessageHandler} implementation type.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
@@ -170,15 +173,19 @@ public abstract class ConsumerEndpointSpec<S extends ConsumerEndpointSpec<S, H>,
|
||||
/**
|
||||
* @param sendTimeout the send timeout.
|
||||
* @return the endpoint spec.
|
||||
* @see AbstractReplyProducingMessageHandler#setSendTimeout(long)
|
||||
* @see AbstractMessageProducingHandler#setSendTimeout(long)
|
||||
*/
|
||||
public S sendTimeout(long sendTimeout) {
|
||||
assertHandler();
|
||||
if (this.handler instanceof AbstractReplyProducingMessageHandler) {
|
||||
((AbstractReplyProducingMessageHandler) this.handler).setSendTimeout(sendTimeout);
|
||||
if (this.handler instanceof AbstractMessageProducingHandler) {
|
||||
((AbstractMessageProducingHandler) this.handler).setSendTimeout(sendTimeout);
|
||||
}
|
||||
else if (this.handler instanceof AbstractMessageRouter) {
|
||||
// This should probably go on the RouterSpec, but we put it here for consistency
|
||||
((AbstractMessageRouter) this.handler).setSendTimeout(sendTimeout);
|
||||
}
|
||||
else {
|
||||
logger.warn("'sendTimeout' can be applied only for AbstractReplyProducingMessageHandler");
|
||||
logger.warn("'sendTimeout' can be applied only for AbstractMessageProducingHandler");
|
||||
}
|
||||
return _this();
|
||||
}
|
||||
@@ -200,20 +207,22 @@ public abstract class ConsumerEndpointSpec<S extends ConsumerEndpointSpec<S, H>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow async replies. If the handler reply is a {@code ListenableFuture} send
|
||||
* the output when it is satisfied rather than sending the future as the result.
|
||||
* Only subclasses that support this feature should set it.
|
||||
* Allow async replies. If the handler reply is a
|
||||
* {@code org.springframework.util.concurrent.ListenableFuture}, send the output when
|
||||
* it is satisfied rather than sending the future as the result. Ignored for handler
|
||||
* return types other than
|
||||
* {@link org.springframework.util.concurrent.ListenableFuture}.
|
||||
* @param async true to allow.
|
||||
* @return the endpoint spec.
|
||||
* @see AbstractReplyProducingMessageHandler#setAsync(boolean)
|
||||
* @see AbstractMessageProducingHandler#setAsync(boolean)
|
||||
*/
|
||||
public S async(boolean async) {
|
||||
assertHandler();
|
||||
if (this.handler instanceof AbstractReplyProducingMessageHandler) {
|
||||
((AbstractReplyProducingMessageHandler) this.handler).setAsync(async);
|
||||
if (this.handler instanceof AbstractMessageProducingHandler) {
|
||||
((AbstractMessageProducingHandler) this.handler).setAsync(async);
|
||||
}
|
||||
else {
|
||||
logger.warn("'async' can be applied only for AbstractReplyProducingMessageHandler");
|
||||
logger.warn("'async' can be applied only for AbstractMessageProducingHandler");
|
||||
}
|
||||
return _this();
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow async replies. If the handler reply is a {@link ListenableFuture} send
|
||||
* Allow async replies. If the handler reply is a {@link ListenableFuture}, send
|
||||
* the output when it is satisfied rather than sending the future as the result.
|
||||
* Only subclasses that support this feature should set it.
|
||||
* Ignored for return types other than {@link ListenableFuture}.
|
||||
* @param async true to allow.
|
||||
* @since 4.3
|
||||
*/
|
||||
|
||||
@@ -589,6 +589,55 @@ The example below demonstrates a `PayloadTypeRouter` configuration which is equi
|
||||
</int:payload-type-router>
|
||||
----
|
||||
|
||||
The equivalent router, using Java configuration:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@ServiceActivator(inputChannel = "routingChannel")
|
||||
@Bean
|
||||
public PayloadTypeRouter router() {
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setChannelMapping(String.class.getName(), "stringChannel");
|
||||
router.setChannelMapping(Integer.class.getName(), "integerChannel");
|
||||
return router;
|
||||
}
|
||||
----
|
||||
|
||||
When using the Java DSL, there are two options; 1) define the router object as above...
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow1() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
.route(router())
|
||||
.get();
|
||||
}
|
||||
|
||||
public PayloadTypeRouter router() {
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setChannelMapping(String.class.getName(), "stringChannel");
|
||||
router.setChannelMapping(Integer.class.getName(), "integerChannel");
|
||||
return router;
|
||||
}
|
||||
----
|
||||
|
||||
Note that the router can be, but doesn't have to be, a `@Bean` - the flow will register it if it is not.
|
||||
|
||||
2) define the routing function within the DSL flow itself...
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow2() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
.<Object, Class<?>>route(Object::getClass, m -> m
|
||||
.channelMapping(String.class, "stringChannel")
|
||||
.channelMapping(Integer.class, "integerChannel"))
|
||||
.get();
|
||||
}
|
||||
----
|
||||
|
||||
[[router-implementations-headervaluerouter]]
|
||||
===== HeaderValueRouter
|
||||
|
||||
@@ -627,6 +676,56 @@ However, in cases where the header value is mapped to a channel name but the cha
|
||||
IMPORTANT: With Spring Integration 2.1 the attribute was changed from `ignore-channel-name-resolution-failures` to `resolution-required`.
|
||||
Attribute `resolution-required` will default to `true`.
|
||||
|
||||
The equivalent router, using Java configuration:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@ServiceActivator(inputChannel = "routingChannel")
|
||||
@Bean
|
||||
public HeaderValueRouter router() {
|
||||
HeaderValueRouter router = new HeaderValueRouter("testHeader");
|
||||
router.setChannelMapping("someHeaderValue", "channelA");
|
||||
router.setChannelMapping("someOtherHeaderValue", "channelB");
|
||||
return router;
|
||||
}
|
||||
----
|
||||
|
||||
When using the Java DSL, there are two options; 1) define the router object as above...
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow1() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
.route(router())
|
||||
.get();
|
||||
}
|
||||
|
||||
public HeaderValueRouter router() {
|
||||
HeaderValueRouter router = new HeaderValueRouter("testHeader");
|
||||
router.setChannelMapping("someHeaderValue", "channelA");
|
||||
router.setChannelMapping("someOtherHeaderValue", "channelB");
|
||||
return router;
|
||||
}
|
||||
----
|
||||
|
||||
Note that the router can be, but doesn't have to be, a `@Bean` - the flow will register it if it is not.
|
||||
|
||||
2) define the routing function within the DSL flow itself...
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow2() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
.<Message<?>, String>route(m -> m.getHeaders().get("testHeader", String.class), m -> m
|
||||
.channelMapping("someHeaderValue", "channelA")
|
||||
.channelMapping("someOtherHeaderValue", "channelB"),
|
||||
e -> e.id("headerValueRouter"))
|
||||
.get();
|
||||
}
|
||||
----
|
||||
|
||||
_2.
|
||||
Configuration where mapping of header values to channel names
|
||||
is not required since header values themselves represent channel names_
|
||||
@@ -676,8 +775,45 @@ Spring Integration also provides namespace support for the `RecipientListRouter`
|
||||
</int:recipient-list-router>
|
||||
----
|
||||
|
||||
The equivalent router, using Java configuration:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@ServiceActivator(inputChannel = "routingChannel")
|
||||
@Bean
|
||||
public RecipientListRouter router() {
|
||||
RecipientListRouter router = new RecipientListRouter();
|
||||
router.setSendTimeout(1_234L);
|
||||
router.setIgnoreSendFailures(true);
|
||||
router.setApplySequence(true);
|
||||
router.addRecipient("channel1");
|
||||
router.addRecipient("channel2");
|
||||
router.addRecipient("channel3");
|
||||
return router;
|
||||
}
|
||||
----
|
||||
|
||||
The equivalent router, using the Java DSL:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
.routeToRecipients(r -> r
|
||||
.applySequence(true)
|
||||
.ignoreSendFailures(true)
|
||||
.recipient("channel1")
|
||||
.recipient("channel2")
|
||||
.recipient("channel3"), c -> c.sendTimeout(1_234L))
|
||||
.get();
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
NOTE: The 'apply-sequence' flag here has the same effect as it does for a publish-subscribe-channel, and like a publish-subscribe-channel, it is disabled by default on the recipient-list-router.
|
||||
Refer to<<channel-configuration-pubsubchannel>> for more information.
|
||||
Refer to <<channel-configuration-pubsubchannel>> for more information.
|
||||
|
||||
Another convenient option when configuring a `RecipientListRouter` is to use Spring Expression Language (SpEL) support as selectors for individual recipient channels.
|
||||
This is similar to using a Filter at the beginning of 'chain' to act as a "Selective Consumer".
|
||||
|
||||
Reference in New Issue
Block a user