Add route(), recipientListRoute() EIP-methods

This commit is contained in:
Artem Bilan
2014-03-14 13:37:31 +02:00
parent 53b25dbdcf
commit 4cf18e71c8
7 changed files with 693 additions and 55 deletions

View File

@@ -56,7 +56,10 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.MessageDispatchingException;
import org.springframework.integration.annotation.Header;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.FixedSubscriberChannel;
@@ -79,6 +82,7 @@ import org.springframework.integration.file.DefaultFileNameGenerator;
import org.springframework.integration.file.FileHeaders;
import org.springframework.integration.file.FileWritingMessageHandler;
import org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice;
import org.springframework.integration.router.MethodInvokingRouter;
import org.springframework.integration.scheduling.PollerMetadata;
import org.springframework.integration.splitter.DefaultMessageSplitter;
import org.springframework.integration.store.SimpleMessageStore;
@@ -91,7 +95,9 @@ import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.core.DestinationResolutionException;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;
@@ -110,8 +116,7 @@ public class IntegrationFlowTests {
private ListableBeanFactory beanFactory;
@Autowired
@Qualifier("controlBus")
private MessageChannel controlBus;
private ControlBusGateway controlBus;
@Autowired
@Qualifier("flow1QueueChannel")
@@ -184,6 +189,49 @@ public class IntegrationFlowTests {
@Qualifier("splitAggregateInput")
private MessageChannel splitAggregateInput;
@Autowired
@Qualifier("routerInput")
private MessageChannel routerInput;
@Autowired
@Qualifier("oddChannel")
private PollableChannel oddChannel;
@Autowired
@Qualifier("evenChannel")
private PollableChannel evenChannel;
@Autowired
@Qualifier("routerMethodInput")
private MessageChannel routerMethodInput;
@Autowired
@Qualifier("foo-channel")
private PollableChannel fooChannel;
@Autowired
@Qualifier("bar-channel")
private PollableChannel barChannel;
@Autowired
@Qualifier("routerMethod2Input")
private MessageChannel routerMethod2Input;
@Autowired
@Qualifier("routerMethod3Input")
private MessageChannel routerMethod3Input;
@Autowired
@Qualifier("routerMultiInput")
private MessageChannel routerMultiInput;
@Autowired
@Qualifier("recipientListInput")
private MessageChannel recipientListInput;
@Autowired
@Qualifier("defaultOutputChannel")
private QueueChannel defaultOutputChannel;
@Test
public void testPollingFlow() {
@@ -210,7 +258,7 @@ public class IntegrationFlowTests {
assertThat(e.getCause(), Matchers.instanceOf(MessageDispatchingException.class));
assertThat(e.getMessage(), Matchers.containsString("Dispatcher has no subscribers"));
}
this.controlBus.send(new GenericMessage<Object>("@payloadSerializingTransformer.start()"));
this.controlBus.send("@payloadSerializingTransformer.start()");
final AtomicBoolean used = new AtomicBoolean();
@@ -256,7 +304,7 @@ public class IntegrationFlowTests {
assertThat(e.getCause(), Matchers.instanceOf(MessageDispatchingException.class));
assertThat(e.getMessage(), Matchers.containsString("Dispatcher has no subscribers"));
}
this.controlBus.send(new GenericMessage<Object>("@bridge.start()"));
this.controlBus.send("@bridge.start()");
this.bridgeFlow2Input.send(message);
reply = this.bridgeFlow2Output.receive(5000);
assertNotNull(reply);
@@ -399,7 +447,7 @@ public class IntegrationFlowTests {
assertThat(e.getMessage(), Matchers.containsString("Dispatcher has no subscribers"));
}
this.controlBus.send(new GenericMessage<Object>("@xpathHeaderEnricher.start()"));
this.controlBus.send("@xpathHeaderEnricher.start()");
this.xpathHeaderEnricherInput.send(message);
Message<?> result = replyChannel.receive(2000);
@@ -409,8 +457,188 @@ public class IntegrationFlowTests {
assertEquals("2", headers.get("two"));
}
@Test
public void testRouter() {
int[] payloads = new int[]{1, 2, 3, 4, 5, 6};
for (int payload : payloads) {
this.routerInput.send(new GenericMessage<Integer>(payload));
}
for (int i = 0; i < 3; i++) {
Message<?> receive = this.oddChannel.receive(2000);
assertNotNull(receive);
assertEquals(new Integer(i * 2 + 1), receive.getPayload());
receive = this.evenChannel.receive(2000);
assertNotNull(receive);
assertEquals(new Integer(i * 2 + 2), receive.getPayload());
}
}
@Test
public void testMethodInvokingRouter() {
Message<String> fooMessage = new GenericMessage<String>("foo");
Message<String> barMessage = new GenericMessage<String>("bar");
Message<String> badMessage = new GenericMessage<String>("bad");
this.routerMethodInput.send(fooMessage);
Message<?> result1a = this.fooChannel.receive(2000);
assertNotNull(result1a);
assertEquals("foo", result1a.getPayload());
assertNull(this.barChannel.receive(0));
this.routerMethodInput.send(barMessage);
assertNull(this.fooChannel.receive(0));
Message<?> result2b = this.barChannel.receive(2000);
assertNotNull(result2b);
assertEquals("bar", result2b.getPayload());
try {
this.routerMethodInput.send(badMessage);
fail("MessageDeliveryException expected.");
}
catch (MessageDeliveryException e) {
assertThat(e.getMessage(), Matchers.containsString("no channel resolved by router and no default output channel defined"));
}
}
@Test
public void testMethodInvokingRouter2() {
Message<String> fooMessage = MessageBuilder.withPayload("foo").setHeader("targetChannel", "foo").build();
Message<String> barMessage = MessageBuilder.withPayload("bar").setHeader("targetChannel", "bar").build();
Message<String> badMessage = MessageBuilder.withPayload("bad").setHeader("targetChannel", "bad").build();
this.routerMethod2Input.send(fooMessage);
Message<?> result1a = this.fooChannel.receive(2000);
assertNotNull(result1a);
assertEquals("foo", result1a.getPayload());
assertNull(this.barChannel.receive(0));
this.routerMethod2Input.send(barMessage);
assertNull(this.fooChannel.receive(0));
Message<?> result2b = this.barChannel.receive(2000);
assertNotNull(result2b);
assertEquals("bar", result2b.getPayload());
try {
this.routerMethod2Input.send(badMessage);
fail("DestinationResolutionException expected.");
}
catch (MessagingException e) {
assertThat(e.getCause(), Matchers.instanceOf(DestinationResolutionException.class));
assertThat(e.getCause().getMessage(), Matchers.containsString("failed to look up MessageChannel with name 'bad-channel'"));
}
}
@Test
public void testMethodInvokingRouter3() {
Message<String> fooMessage = new GenericMessage<String>("foo");
Message<String> barMessage = new GenericMessage<String>("bar");
Message<String> badMessage = new GenericMessage<String>("bad");
this.routerMethod3Input.send(fooMessage);
Message<?> result1a = this.fooChannel.receive(2000);
assertNotNull(result1a);
assertEquals("foo", result1a.getPayload());
assertNull(this.barChannel.receive(0));
this.routerMethod3Input.send(barMessage);
assertNull(this.fooChannel.receive(0));
Message<?> result2b = this.barChannel.receive(2000);
assertNotNull(result2b);
assertEquals("bar", result2b.getPayload());
try {
this.routerMethod3Input.send(badMessage);
fail("DestinationResolutionException expected.");
}
catch (MessagingException e) {
assertThat(e.getCause(), Matchers.instanceOf(DestinationResolutionException.class));
assertThat(e.getCause().getMessage(), Matchers.containsString("failed to look up MessageChannel with name 'bad-channel'"));
}
}
@Test
public void testMultiRouter() {
Message<String> fooMessage = new GenericMessage<String>("foo");
Message<String> barMessage = new GenericMessage<String>("bar");
Message<String> badMessage = new GenericMessage<String>("bad");
this.routerMultiInput.send(fooMessage);
Message<?> result1a = this.fooChannel.receive(2000);
assertNotNull(result1a);
assertEquals("foo", result1a.getPayload());
Message<?> result1b = this.barChannel.receive(2000);
assertNotNull(result1b);
assertEquals("foo", result1b.getPayload());
this.routerMultiInput.send(barMessage);
Message<?> result2a = this.fooChannel.receive(2000);
assertNotNull(result2a);
assertEquals("bar", result2a.getPayload());
Message<?> result2b = this.barChannel.receive(2000);
assertNotNull(result2b);
assertEquals("bar", result2b.getPayload());
try {
this.routerMultiInput.send(badMessage);
fail("MessageDeliveryException expected.");
}
catch (MessageDeliveryException e) {
assertThat(e.getMessage(), Matchers.containsString("no channel resolved by router and no default output channel defined"));
}
}
@Test
public void testRecipientListRouter() {
Message<String> fooMessage = MessageBuilder.withPayload("fooPayload").setHeader("recipient", true).build();
Message<String> barMessage = MessageBuilder.withPayload("barPayload").setHeader("recipient", true).build();
Message<String> badMessage = new GenericMessage<String>("badPayload");
this.recipientListInput.send(fooMessage);
Message<?> result1a = this.fooChannel.receive(2000);
assertNotNull(result1a);
assertEquals("foo", result1a.getPayload());
Message<?> result1b = this.barChannel.receive(2000);
assertNotNull(result1b);
assertEquals("foo", result1b.getPayload());
this.recipientListInput.send(barMessage);
assertNull(this.fooChannel.receive(0));
Message<?> result2b = this.barChannel.receive(2000);
assertNotNull(result2b);
assertEquals("bar", result2b.getPayload());
this.recipientListInput.send(badMessage);
assertNull(this.fooChannel.receive(0));
assertNull(this.barChannel.receive(0));
Message<?> result3c = this.defaultOutputChannel.receive(2000);
assertNotNull(result3c);
assertEquals("bad", result3c.getPayload());
}
@MessagingGateway(defaultRequestChannel = "controlBus")
private static interface ControlBusGateway {
void send(String command);
}
@Configuration
@EnableIntegration
@IntegrationComponentScan
public static class ContextConfiguration {
@Bean
@@ -552,6 +780,33 @@ public class IntegrationFlowTests {
.get();
}
@Bean(name = "foo-channel")
public QueueChannel fooChannel() {
return new QueueChannel();
}
@Bean(name = "bar-channel")
public QueueChannel barChannel() {
return new QueueChannel();
}
@Bean
public QueueChannel defaultOutputChannel() {
return new QueueChannel();
}
@Bean
public IntegrationFlow recipientListFlow() {
return IntegrationFlows.from("recipientListInput")
.<String, String>transform(p -> p.replaceFirst("Payload", ""))
.recipientListRoute(r ->
r.defaultOutputChannel(defaultOutputChannel())
.recipient("foo-channel", "'foo' == payload")
.recipient("bar-channel", m ->
m.getHeaders().containsKey("recipient") && (boolean) m.getHeaders().get("recipient"))
)
.get();
}
}
@Component("delayedAdvice")
@@ -679,6 +934,83 @@ public class IntegrationFlowTests {
.get();
}
@Bean
public QueueChannel oddChannel() {
return new QueueChannel();
}
@Bean
public QueueChannel evenChannel() {
return new QueueChannel();
}
@Bean
public IntegrationFlow routeFlow() {
return IntegrationFlows.from("routerInput")
.<Integer, Boolean>route(p -> p % 2 == 0,
m -> m.suffix("Channel")
.channelMapping("true", "even")
.channelMapping("false", "odd")
)
.get();
}
@Bean
public RoutingTestBean routingTestBean() {
return new RoutingTestBean();
}
@Bean
public IntegrationFlow routeMethodInvocationFlow() {
return IntegrationFlows.from("routerMethodInput")
.route("routingTestBean", "routeMessage")
.get();
}
@Bean
public IntegrationFlow routeMethodInvocationFlow2() {
return IntegrationFlows.from("routerMethod2Input")
.route(new MethodInvokingRouter(new RoutingTestBean(), "routeByHeader"))
.get();
}
@Bean
public IntegrationFlow routeMethodInvocationFlow3() {
return IntegrationFlows.from("routerMethod3Input")
.route((String p) -> ContextConfiguration4.this.routingTestBean().routePayload(p))
.get();
}
@Bean
public IntegrationFlow routeMultiMethodInvocationFlow() {
return IntegrationFlows.from("routerMultiInput")
.<String, String[]>route(p -> p.equals("foo") || p.equals("bar") ? new String[]{"foo", "bar"} : null,
s -> s.suffix("-channel")
)
.get();
}
}
private static class RoutingTestBean {
public String routePayload(String name) {
return name + "-channel";
}
public String routeByHeader(@Header("targetChannel") String name) {
return name + "-channel";
}
public String routeMessage(Message<?> message) {
if (message.getPayload().equals("foo")) {
return "foo-channel";
}
else if (message.getPayload().equals("bar")) {
return "bar-channel";
}
return null;
}
}
@Component("greetingService")
@@ -695,7 +1027,7 @@ public class IntegrationFlowTests {
@Bean
public IntegrationFlow wrongLastComponent() {
return IntegrationFlows.from(MessageChannels.direct())
.handle(Object::toString)
.route(Object::toString)
.channel(MessageChannels.direct())
.get();
}