Java tutorial
/* * Copyright 2014 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.dsl.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.isOneOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import com.jcraft.jsch.ChannelSftp; import com.mongodb.MongoClient; import de.flapdoodle.embed.mongo.MongodExecutable; import de.flapdoodle.embed.mongo.MongodStarter; import de.flapdoodle.embed.mongo.config.MongodConfigBuilder; import de.flapdoodle.embed.mongo.config.Net; import de.flapdoodle.embed.mongo.distribution.Version; import de.flapdoodle.embed.process.runtime.Network; import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.net.ftp.FTPFile; import org.hamcrest.Matchers; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.amqp.core.AnonymousQueue; import org.springframework.amqp.core.Queue; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.Advised; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.ConfigFileApplicationContextInitializer; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.MessageDispatchingException; import org.springframework.integration.MessageRejectedException; 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.ChannelInterceptorAware; import org.springframework.integration.channel.FixedSubscriberChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.integration.config.GlobalChannelInterceptor; import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.core.MessageSource; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.dsl.amqp.Amqp; import org.springframework.integration.dsl.channel.DirectChannelSpec; import org.springframework.integration.dsl.channel.MessageChannels; import org.springframework.integration.dsl.file.File; import org.springframework.integration.dsl.ftp.Ftp; import org.springframework.integration.dsl.jms.Jms; import org.springframework.integration.dsl.sftp.Sftp; import org.springframework.integration.dsl.support.Pollers; import org.springframework.integration.dsl.support.Transformers; import org.springframework.integration.endpoint.MethodInvokingMessageSource; import org.springframework.integration.event.core.MessagingEvent; import org.springframework.integration.event.outbound.ApplicationEventPublishingMessageHandler; import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.FileHeaders; import org.springframework.integration.file.remote.RemoteFileTemplate; import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway; import org.springframework.integration.ftp.session.DefaultFtpSessionFactory; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice; import org.springframework.integration.mongodb.store.MongoDbChannelMessageStore; import org.springframework.integration.router.MethodInvokingRouter; import org.springframework.integration.scheduling.PollerMetadata; import org.springframework.integration.sftp.session.DefaultSftpSessionFactory; import org.springframework.integration.store.MessageStore; import org.springframework.integration.store.PriorityCapableChannelMessageStore; import org.springframework.integration.store.SimpleMessageStore; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.support.MutableMessageBuilder; import org.springframework.integration.test.util.TestUtils; import org.springframework.integration.transformer.PayloadDeserializingTransformer; import org.springframework.integration.transformer.PayloadSerializingTransformer; import org.springframework.integration.xml.transformer.support.XPathExpressionEvaluatingHeaderValueMessageProcessor; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.support.ChannelInterceptorAdapter; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.StreamUtils; /** * @author Artem Bilan * @author Tim Ysewyn */ @ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) @RunWith(SpringJUnit4ClassRunner.class) @DirtiesContext public class IntegrationFlowTests { private static final java.io.File tmpDir = new java.io.File(System.getProperty("java.io.tmpdir")); private static int mongoPort; private static MongodExecutable mongodExe; @Autowired private ListableBeanFactory beanFactory; @Autowired private ControlBusGateway controlBus; @Autowired @Qualifier("flow1QueueChannel") private PollableChannel outputChannel; @Autowired private TestChannelInterceptor testChannelInterceptor; @Autowired @Qualifier("inputChannel") private MessageChannel inputChannel; @Autowired @Qualifier("foo") private SubscribableChannel foo; @Autowired @Qualifier("successChannel") private PollableChannel successChannel; @Autowired @Qualifier("flow3Input") private MessageChannel flow3Input; @Autowired private AtomicReference<Object> eventHolder; @Autowired @Qualifier("bridgeFlowInput") private PollableChannel bridgeFlowInput; @Autowired @Qualifier("bridgeFlowOutput") private PollableChannel bridgeFlowOutput; @Autowired @Qualifier("bridgeFlow2Input") private MessageChannel bridgeFlow2Input; @Autowired @Qualifier("bridgeFlow2Output") private PollableChannel bridgeFlow2Output; @Autowired @Qualifier("fileFlow1Input") private MessageChannel fileFlow1Input; @Autowired @Qualifier("fileWriting.handler") private MessageHandler fileWritingMessageHandler; @Autowired @Qualifier("methodInvokingInput") private MessageChannel methodInvokingInput; @Autowired @Qualifier("delayedAdvice") private DelayedAdvice delayedAdvice; @Autowired @Qualifier("enricherInput") private FixedSubscriberChannel enricherInput; @Autowired @Qualifier("enricherInput2") private FixedSubscriberChannel enricherInput2; @Autowired @Qualifier("enricherInput3") private FixedSubscriberChannel enricherInput3; @Autowired @Qualifier("splitInput") private MessageChannel splitInput; @Autowired @Qualifier("xpathHeaderEnricherInput") private MessageChannel xpathHeaderEnricherInput; @Autowired @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 PollableChannel defaultOutputChannel; @Autowired private MessageStore messageStore; @Autowired @Qualifier("claimCheckInput") private MessageChannel claimCheckInput; @Autowired @Qualifier("priorityChannel") private MessageChannel priorityChannel; @Autowired @Qualifier("priorityReplyChannel") private PollableChannel priorityReplyChannel; @Autowired @Qualifier("lamdasInput") private MessageChannel lamdasInput; @Autowired @Qualifier("tailChannel") private PollableChannel tailChannel; @Autowired private AmqpTemplate amqpTemplate; @Autowired @Qualifier("queue") private Queue amqpQueue; @Autowired @Qualifier("gatewayInput") private MessageChannel gatewayInput; @Autowired @Qualifier("gatewayError") private PollableChannel gatewayError; @BeforeClass public static void setup() throws IOException { mongoPort = Network.getFreeServerPort(); mongodExe = MongodStarter.getDefaultInstance().prepare(new MongodConfigBuilder() .version(Version.Main.PRODUCTION).net(new Net(mongoPort, Network.localhostIsIPv6())).build()); mongodExe.start(); } @AfterClass public static void tearDown() { mongodExe.stop(); } @Test public void testPollingFlow() { this.controlBus.send("@integerEndpoint.start()"); assertThat(this.beanFactory.getBean("integerChannel"), instanceOf(FixedSubscriberChannel.class)); for (int i = 0; i < 5; i++) { Message<?> message = this.outputChannel.receive(20000); assertNotNull(message); assertEquals("" + i, message.getPayload()); } this.controlBus.send("@integerEndpoint.stop()"); assertTrue(((ChannelInterceptorAware) this.outputChannel).getChannelInterceptors() .contains(this.testChannelInterceptor)); assertThat(this.testChannelInterceptor.getInvoked(), Matchers.greaterThanOrEqualTo(5)); } @Test public void testDirectFlow() { assertTrue(this.beanFactory.containsBean("filter")); assertTrue(this.beanFactory.containsBean("filter.handler")); QueueChannel replyChannel = new QueueChannel(); Message<String> message = MessageBuilder.withPayload("100").setReplyChannel(replyChannel).build(); try { this.inputChannel.send(message); fail("Expected MessageDispatchingException"); } catch (Exception e) { assertThat(e, instanceOf(MessageDeliveryException.class)); assertThat(e.getCause(), instanceOf(MessageDispatchingException.class)); assertThat(e.getMessage(), containsString("Dispatcher has no subscribers")); } this.controlBus.send("@payloadSerializingTransformer.start()"); final AtomicBoolean used = new AtomicBoolean(); this.foo.subscribe(m -> used.set(true)); this.inputChannel.send(message); Message<?> reply = replyChannel.receive(5000); assertNotNull(reply); assertEquals(200, reply.getPayload()); Message<?> successMessage = this.successChannel.receive(5000); assertNotNull(successMessage); assertEquals(100, successMessage.getPayload()); assertTrue(used.get()); } @Test public void testHandle() { assertNull(this.eventHolder.get()); this.flow3Input.send(new GenericMessage<>("2")); assertNotNull(this.eventHolder.get()); assertEquals(4, this.eventHolder.get()); } @Test public void testBridge() { GenericMessage<String> message = new GenericMessage<>("test"); this.bridgeFlowInput.send(message); Message<?> reply = this.bridgeFlowOutput.receive(5000); assertNotNull(reply); assertEquals("test", reply.getPayload()); assertTrue(this.beanFactory.containsBean("bridgeFlow2.channel#0")); assertThat(this.beanFactory.getBean("bridgeFlow2.channel#0"), instanceOf(FixedSubscriberChannel.class)); try { this.bridgeFlow2Input.send(message); fail("Expected MessageDispatchingException"); } catch (Exception e) { assertThat(e, instanceOf(MessageDeliveryException.class)); assertThat(e.getCause(), instanceOf(MessageDispatchingException.class)); assertThat(e.getMessage(), containsString("Dispatcher has no subscribers")); } this.controlBus.send("@bridge.start()"); this.bridgeFlow2Input.send(message); reply = this.bridgeFlow2Output.receive(5000); assertNotNull(reply); assertEquals("test", reply.getPayload()); assertTrue(this.delayedAdvice.getInvoked()); } @Test public void testWrongLastComponent() { ConfigurableApplicationContext context = null; try { context = new AnnotationConfigApplicationContext(InvalidLastComponentFlowContext.class); fail("BeanCreationException expected"); } catch (Exception e) { assertThat(e, instanceOf(BeanCreationException.class)); assertThat(e.getMessage(), containsString("is a one-way 'MessageHandler'")); } finally { if (context != null) { context.close(); } } } @Test public void testWrongLastMessageChannel() { ConfigurableApplicationContext context = null; try { context = new AnnotationConfigApplicationContext(InvalidLastMessageChannelFlowContext.class); fail("BeanCreationException expected"); } catch (Exception e) { assertThat(e, instanceOf(BeanCreationException.class)); assertThat(e.getMessage(), containsString("'.fixedSubscriberChannel()' " + "can't be the last EIP-method in the IntegrationFlow definition")); } finally { if (context != null) { context.close(); } } } @Test public void testFileHandler() throws Exception { Message<?> message = MessageBuilder.withPayload("foo").setHeader(FileHeaders.FILENAME, "foo").build(); try { this.fileFlow1Input.send(message); fail("NullPointerException expected"); } catch (Exception e) { assertThat(e, instanceOf(MessageHandlingException.class)); assertThat(e.getCause(), instanceOf(NullPointerException.class)); } DefaultFileNameGenerator fileNameGenerator = new DefaultFileNameGenerator(); fileNameGenerator.setBeanFactory(this.beanFactory); Object targetFileWritingMessageHandler = this.fileWritingMessageHandler; if (this.fileWritingMessageHandler instanceof Advised) { TargetSource targetSource = ((Advised) this.fileWritingMessageHandler).getTargetSource(); if (targetSource != null) { targetFileWritingMessageHandler = targetSource.getTarget(); } } DirectFieldAccessor dfa = new DirectFieldAccessor(targetFileWritingMessageHandler); dfa.setPropertyValue("fileNameGenerator", fileNameGenerator); this.fileFlow1Input.send(message); assertTrue(new java.io.File(tmpDir, "foo").exists()); } @Test public void testMethodInvokingMessageHandler() { QueueChannel replyChannel = new QueueChannel(); Message<?> message = MessageBuilder.withPayload("world") .setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel).build(); this.methodInvokingInput.send(message); Message<?> receive = replyChannel.receive(5000); assertNotNull(receive); assertEquals("Hello World and world", receive.getPayload()); } @Test public void testLambdas() { QueueChannel replyChannel = new QueueChannel(); Message<?> message = MessageBuilder.withPayload("World") .setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel).build(); this.lamdasInput.send(message); Message<?> receive = replyChannel.receive(5000); assertNotNull(receive); assertEquals("Hello World", receive.getPayload()); message = MessageBuilder.withPayload("Spring").setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel) .build(); this.lamdasInput.send(message); assertNull(replyChannel.receive(10)); } @Test public void testWrongConfigurationWithSpecBean() { ConfigurableApplicationContext context = null; try { context = new AnnotationConfigApplicationContext(InvalidConfigurationWithSpec.class); fail("BeanCreationException expected"); } catch (Exception e) { assertThat(e, instanceOf(IllegalArgumentException.class)); assertThat(e.getCause(), instanceOf(BeanCreationException.class)); assertThat(e.getCause().getMessage(), containsString("must be populated to target objects via 'get()' method call")); } finally { if (context != null) { context.close(); } } } @Test public void testContentEnricher() { QueueChannel replyChannel = new QueueChannel(); Message<?> message = MessageBuilder.withPayload(new TestPojo("Bar")) .setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel).build(); this.enricherInput.send(message); Message<?> receive = replyChannel.receive(5000); assertNotNull(receive); assertEquals("Bar Bar", receive.getHeaders().get("foo")); Object payload = receive.getPayload(); assertThat(payload, instanceOf(TestPojo.class)); TestPojo result = (TestPojo) payload; assertEquals("Bar Bar", result.getName()); assertNotNull(result.getDate()); assertThat(new Date(), Matchers.greaterThanOrEqualTo(result.getDate())); } @Test public void testContentEnricher2() { QueueChannel replyChannel = new QueueChannel(); Message<?> message = MessageBuilder.withPayload(new TestPojo("Bar")) .setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel).build(); this.enricherInput2.send(message); Message<?> receive = replyChannel.receive(5000); assertNotNull(receive); assertNull(receive.getHeaders().get("foo")); Object payload = receive.getPayload(); assertThat(payload, instanceOf(TestPojo.class)); TestPojo result = (TestPojo) payload; assertEquals("Bar Bar", result.getName()); assertNotNull(result.getDate()); assertThat(new Date(), Matchers.greaterThanOrEqualTo(result.getDate())); } @Test public void testContentEnricher3() { QueueChannel replyChannel = new QueueChannel(); Message<?> message = MessageBuilder.withPayload(new TestPojo("Bar")) .setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel).build(); this.enricherInput3.send(message); Message<?> receive = replyChannel.receive(5000); assertNotNull(receive); assertEquals("Bar Bar", receive.getHeaders().get("foo")); Object payload = receive.getPayload(); assertThat(payload, instanceOf(TestPojo.class)); TestPojo result = (TestPojo) payload; assertEquals("Bar", result.getName()); assertNull(result.getDate()); } @Test public void testSplitterResequencer() { QueueChannel replyChannel = new QueueChannel(); this.splitInput .send(MessageBuilder.withPayload("").setReplyChannel(replyChannel).setHeader("foo", "bar").build()); for (int i = 0; i < 12; i++) { Message<?> receive = replyChannel.receive(2000); assertNotNull(receive); assertFalse(receive.getHeaders().containsKey("foo")); assertTrue(receive.getHeaders().containsKey("FOO")); assertEquals("BAR", receive.getHeaders().get("FOO")); assertEquals(i + 1, receive.getPayload()); } } @Test public void testSplitterAggregator() { List<Character> payload = Arrays.asList('a', 'b', 'c', 'd', 'e'); QueueChannel replyChannel = new QueueChannel(); this.splitAggregateInput.send(MessageBuilder.withPayload(payload).setReplyChannel(replyChannel).build()); Message<?> receive = replyChannel.receive(2000); assertNotNull(receive); assertThat(receive.getPayload(), instanceOf(List.class)); @SuppressWarnings("unchecked") List<Object> result = (List<Object>) receive.getPayload(); for (int i = 0; i < payload.size(); i++) { assertEquals(payload.get(i), result.get(i)); } } @Test public void testHeaderEnricher() { QueueChannel replyChannel = new QueueChannel(); Message<String> message = MessageBuilder .withPayload("<root><elementOne>1</elementOne><elementTwo>2</elementTwo></root>") .setReplyChannel(replyChannel).build(); try { this.xpathHeaderEnricherInput.send(message); fail("Expected MessageDispatchingException"); } catch (Exception e) { assertThat(e, instanceOf(MessageDeliveryException.class)); assertThat(e.getCause(), instanceOf(MessageDispatchingException.class)); assertThat(e.getMessage(), containsString("Dispatcher has no subscribers")); } this.controlBus.send("@xpathHeaderEnricher.start()"); this.xpathHeaderEnricherInput.send(message); Message<?> result = replyChannel.receive(2000); assertNotNull(result); MessageHeaders headers = result.getHeaders(); assertEquals("1", headers.get("one")); assertEquals("2", headers.get("two")); assertThat(headers.getReplyChannel(), instanceOf(String.class)); } @Test public void testRouter() { int[] payloads = new int[] { 1, 2, 3, 4, 5, 6 }; for (int payload : payloads) { this.routerInput.send(new GenericMessage<>(payload)); } for (int i = 0; i < 3; i++) { Message<?> receive = this.oddChannel.receive(2000); assertNotNull(receive); assertEquals(i * 2 + 1, receive.getPayload()); receive = this.evenChannel.receive(2000); assertNotNull(receive); assertEquals(i * 2 + 2, receive.getPayload()); } } @Test public void testMethodInvokingRouter() { Message<String> fooMessage = new GenericMessage<>("foo"); Message<String> barMessage = new GenericMessage<>("bar"); Message<String> badMessage = new GenericMessage<>("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(), 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(), instanceOf(DestinationResolutionException.class)); assertThat(e.getCause().getMessage(), containsString("failed to look up MessageChannel with name 'bad-channel'")); } } @Test public void testMethodInvokingRouter3() { Message<String> fooMessage = new GenericMessage<>("foo"); Message<String> barMessage = new GenericMessage<>("bar"); Message<String> badMessage = new GenericMessage<>("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(), instanceOf(DestinationResolutionException.class)); assertThat(e.getCause().getMessage(), containsString("failed to look up MessageChannel with name 'bad-channel'")); } } @Test public void testMultiRouter() { Message<String> fooMessage = new GenericMessage<>("foo"); Message<String> barMessage = new GenericMessage<>("bar"); Message<String> badMessage = new GenericMessage<>("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(), 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<>("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()); } @Test public void testClaimCheck() { QueueChannel replyChannel = new QueueChannel(); Message<String> message = MutableMessageBuilder.withPayload("foo").setReplyChannel(replyChannel).build(); this.claimCheckInput.send(message); Message<?> receive = replyChannel.receive(2000); assertNotNull(receive); assertSame(message, receive); assertEquals(1, this.messageStore.getMessageCount()); assertSame(message, this.messageStore.getMessage(message.getHeaders().getId())); } @Test public void testPriority() throws InterruptedException { Message<String> message = MessageBuilder.withPayload("1").setPriority(1).build(); this.priorityChannel.send(message); message = MessageBuilder.withPayload("-1").setPriority(-1).build(); this.priorityChannel.send(message); message = MessageBuilder.withPayload("3").setPriority(3).build(); this.priorityChannel.send(message); message = MessageBuilder.withPayload("0").setPriority(0).build(); this.priorityChannel.send(message); message = MessageBuilder.withPayload("2").setPriority(2).build(); this.priorityChannel.send(message); message = MessageBuilder.withPayload("none").build(); this.priorityChannel.send(message); message = MessageBuilder.withPayload("31").setPriority(3).build(); this.priorityChannel.send(message); this.controlBus.send("@priorityChannelBridge.start()"); Message<?> receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("3", receive.getPayload()); receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("31", receive.getPayload()); receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("2", receive.getPayload()); receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("1", receive.getPayload()); receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("0", receive.getPayload()); receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("-1", receive.getPayload()); receive = this.priorityReplyChannel.receive(2000); assertNotNull(receive); assertEquals("none", receive.getPayload()); this.controlBus.send("@priorityChannelBridge.stop()"); } @Test public void testMessageProducerFlow() throws Exception { FileOutputStream file = new FileOutputStream(new java.io.File(tmpDir, "TailTest")); for (int i = 0; i < 50; i++) { file.write((i + "\n").getBytes()); } for (int i = 0; i < 50; i++) { Message<?> message = this.tailChannel.receive(5000); assertNotNull(message); assertEquals("hello " + i, message.getPayload()); } assertNull(this.tailChannel.receive(1)); this.controlBus.send("@tailer.stop()"); file.close(); } @Test public void testAmqpInboundGatewayFlow() throws Exception { Object result = this.amqpTemplate.convertSendAndReceive(this.amqpQueue.getName(), "world"); assertEquals("HELLO WORLD", result); } @Test public void testGatewayFlow() throws Exception { PollableChannel replyChannel = new QueueChannel(); Message<String> message = MessageBuilder.withPayload("foo").setReplyChannel(replyChannel).build(); this.gatewayInput.send(message); Message<?> receive = replyChannel.receive(2000); assertNotNull(receive); assertEquals("FOO", receive.getPayload()); assertNull(this.gatewayError.receive(1)); message = MessageBuilder.withPayload("bar").setReplyChannel(replyChannel).build(); this.gatewayInput.send(message); receive = replyChannel.receive(1); assertNull(receive); receive = this.gatewayError.receive(2000); assertNotNull(receive); assertThat(receive, instanceOf(ErrorMessage.class)); assertThat(receive.getPayload(), instanceOf(MessageRejectedException.class)); assertThat(((Exception) receive.getPayload()).getMessage(), containsString("' rejected Message")); } @Autowired @Qualifier("amqpOutboundInput") private MessageChannel amqpOutboundInput; @Autowired @Qualifier("amqpReplyChannel.channel") private PollableChannel amqpReplyChannel; @Test public void testAmqpOutboundFlow() throws Exception { this.amqpOutboundInput .send(MessageBuilder.withPayload("hello through the amqp").setHeader("routingKey", "foo").build()); Message<?> receive = null; int i = 0; do { receive = this.amqpReplyChannel.receive(); if (receive != null) { break; } Thread.sleep(100); i++; } while (i < 10); assertNotNull(receive); assertEquals("HELLO THROUGH THE AMQP", receive.getPayload()); } @Autowired @Qualifier("jmsOutboundInboundChannel") private MessageChannel jmsOutboundInboundChannel; @Autowired @Qualifier("jmsOutboundInboundReplyChannel") private PollableChannel jmsOutboundInboundReplyChannel; @Test public void testJmsOutboundInboundFlow() { this.jmsOutboundInboundChannel.send(MessageBuilder.withPayload("hello THROUGH the JMS") .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "jmsInbound").build()); Message<?> receive = this.jmsOutboundInboundReplyChannel.receive(5000); assertNotNull(receive); assertEquals("HELLO THROUGH THE JMS", receive.getPayload()); this.jmsOutboundInboundChannel.send(MessageBuilder.withPayload("hello THROUGH the JMS") .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "jmsMessageDriver").build()); receive = this.jmsOutboundInboundReplyChannel.receive(5000); assertNotNull(receive); assertEquals("hello through the jms", receive.getPayload()); } @Autowired @Qualifier("jmsOutboundGatewayChannel") private MessageChannel jmsOutboundGatewayChannel; @Test public void testJmsPipelineFlow() { PollableChannel replyChannel = new QueueChannel(); Message<String> message = MessageBuilder.withPayload("hello through the jms pipeline") .setReplyChannel(replyChannel).setHeader("destination", "jmsPipelineTest").build(); this.jmsOutboundGatewayChannel.send(message); Message<?> receive = replyChannel.receive(5000); assertNotNull(receive); assertEquals("HELLO THROUGH THE JMS PIPELINE", receive.getPayload()); } @Autowired @Qualifier("fileReadingResultChannel") private PollableChannel fileReadingResultChannel; @Test public void testFileReadingFlow() throws Exception { List<Integer> evens = new ArrayList<>(25); for (int i = 0; i < 50; i++) { boolean even = i % 2 == 0; String extension = even ? ".sitest" : ".foofile"; if (even) { evens.add(i); } FileOutputStream file = new FileOutputStream(new java.io.File(tmpDir, i + extension)); file.write(("" + i).getBytes()); file.flush(); file.close(); } Message<?> message = fileReadingResultChannel.receive(10000); assertNotNull(message); Object payload = message.getPayload(); assertThat(payload, instanceOf(List.class)); @SuppressWarnings("unchecked") List<String> result = (List<String>) payload; assertEquals(25, result.size()); result.forEach(s -> assertTrue(evens.contains(Integer.parseInt(s)))); } @Autowired @Qualifier("fileWritingInput") private MessageChannel fileWritingInput; @Autowired @Qualifier("fileWritingResultChannel") private PollableChannel fileWritingResultChannel; @Test public void testFileWritingFlow() throws Exception { String payload = "Spring Integration"; this.fileWritingInput.send(new GenericMessage<>(payload)); Message<?> receive = this.fileWritingResultChannel.receive(1000); assertNotNull(receive); assertThat(receive.getPayload(), instanceOf(java.io.File.class)); java.io.File resultFile = (java.io.File) receive.getPayload(); assertThat(resultFile.getAbsolutePath(), endsWith(TestUtils.applySystemFileSeparator("fileWritingFlow/foo.sitest"))); String fileContent = StreamUtils.copyToString(new FileInputStream(resultFile), Charset.defaultCharset()); assertEquals(payload, fileContent); } @Autowired private TestFtpServer ftpServer; @Autowired private DefaultFtpSessionFactory ftpSessionFactory; @Autowired private TestSftpServer sftpServer; @Autowired private DefaultSftpSessionFactory sftpSessionFactory; @Before @After public void setupRemoteFileServers() { this.ftpServer.recursiveDelete(this.ftpServer.getTargetLocalDirectory()); this.ftpServer.recursiveDelete(this.ftpServer.getTargetFtpDirectory()); this.sftpServer.recursiveDelete(this.sftpServer.getTargetLocalDirectory()); this.sftpServer.recursiveDelete(this.sftpServer.getTargetSftpDirectory()); } @Autowired @Qualifier("ftpInboundResultChannel") private PollableChannel ftpInboundResultChannel; @Test public void testFtpInboundFlow() { Message<?> message = this.ftpInboundResultChannel.receive(1000); assertNotNull(message); Object payload = message.getPayload(); assertThat(payload, instanceOf(java.io.File.class)); java.io.File file = (java.io.File) payload; assertThat(file.getName(), isOneOf("FTPSOURCE1.TXT.a", "FTPSOURCE2.TXT.a")); assertThat(file.getAbsolutePath(), containsString("ftpTest")); message = this.ftpInboundResultChannel.receive(1000); assertNotNull(message); file = (java.io.File) message.getPayload(); assertThat(file.getName(), isOneOf("FTPSOURCE1.TXT.a", "FTPSOURCE2.TXT.a")); assertThat(file.getAbsolutePath(), containsString("ftpTest")); this.controlBus.send("@ftpInboundAdapter.stop()"); } @Autowired @Qualifier("sftpInboundResultChannel") private PollableChannel sftpInboundResultChannel; @Test public void testSftpInboundFlow() { Message<?> message = this.sftpInboundResultChannel.receive(1000); assertNotNull(message); Object payload = message.getPayload(); assertThat(payload, instanceOf(java.io.File.class)); java.io.File file = (java.io.File) payload; assertThat(file.getName(), isOneOf("SFTPSOURCE1.TXT.a", "SFTPSOURCE2.TXT.a")); assertThat(file.getAbsolutePath(), containsString("sftpTest")); message = this.sftpInboundResultChannel.receive(1000); assertNotNull(message); file = (java.io.File) message.getPayload(); assertThat(file.getName(), isOneOf("SFTPSOURCE1.TXT.a", "SFTPSOURCE2.TXT.a")); assertThat(file.getAbsolutePath(), containsString("sftpTest")); this.controlBus.send("@sftpInboundAdapter.stop()"); } @Autowired @Qualifier("toFtpChannel") private MessageChannel toFtpChannel; @Test public void testFtpOutboundFlow() { String fileName = "foo.file"; this.toFtpChannel.send(MessageBuilder.withPayload("foo").setHeader(FileHeaders.FILENAME, fileName).build()); RemoteFileTemplate<FTPFile> template = new RemoteFileTemplate<>(this.ftpSessionFactory); FTPFile[] files = template.execute( session -> session.list(this.ftpServer.getTargetFtpDirectory().getName() + "/" + fileName)); assertEquals(1, files.length); assertEquals(3, files[0].getSize()); } @Autowired @Qualifier("toSftpChannel") private MessageChannel toSftpChannel; @Test public void testSftpOutboundFlow() { String fileName = "foo.file"; this.toSftpChannel .send(MessageBuilder.withPayload("foo").setHeader(FileHeaders.FILENAME, fileName).build()); RemoteFileTemplate<ChannelSftp.LsEntry> template = new RemoteFileTemplate<>(this.sftpSessionFactory); ChannelSftp.LsEntry[] files = template.execute( session -> session.list(this.sftpServer.getTargetSftpDirectory().getName() + "/" + fileName)); assertEquals(1, files.length); assertEquals(3, files[0].getAttrs().getSize()); } @Autowired @Qualifier("ftpMgetInputChannel") private MessageChannel ftpMgetInputChannel; @Autowired @Qualifier("remoteFileOutputChannel") private PollableChannel remoteFileOutputChannel; @Test @SuppressWarnings("unchecked") public void testFtpMgetFlow() { String dir = "ftpSource/"; this.ftpMgetInputChannel.send(new GenericMessage<Object>(dir + "*")); Message<?> result = this.remoteFileOutputChannel.receive(1000); assertNotNull(result); List<java.io.File> localFiles = (List<java.io.File>) result.getPayload(); // should have filtered ftpSource2.txt assertEquals(2, localFiles.size()); for (java.io.File file : localFiles) { assertThat(file.getPath().replaceAll(Matcher.quoteReplacement(java.io.File.separator), "/"), Matchers.containsString(dir)); } assertThat(localFiles.get(1).getPath().replaceAll(Matcher.quoteReplacement(java.io.File.separator), "/"), Matchers.containsString(dir + "subFtpSource")); } @Autowired @Qualifier("sftpMgetInputChannel") private MessageChannel sftpMgetInputChannel; @Test @SuppressWarnings("unchecked") public void testSftpMgetFlow() { String dir = "sftpSource/"; this.sftpMgetInputChannel.send(new GenericMessage<Object>(dir + "*")); Message<?> result = this.remoteFileOutputChannel.receive(1000); assertNotNull(result); List<java.io.File> localFiles = (List<java.io.File>) result.getPayload(); // should have filtered sftpSource2.txt assertEquals(2, localFiles.size()); for (java.io.File file : localFiles) { assertThat(file.getPath().replaceAll(Matcher.quoteReplacement(java.io.File.separator), "/"), Matchers.containsString(dir)); } assertThat(localFiles.get(1).getPath().replaceAll(Matcher.quoteReplacement(java.io.File.separator), "/"), Matchers.containsString(dir + "subSftpSource")); } @MessagingGateway(defaultRequestChannel = "controlBus") private static interface ControlBusGateway { void send(String command); } @Configuration @EnableAutoConfiguration @IntegrationComponentScan public static class ContextConfiguration { @Bean public MessageSource<?> integerMessageSource() { MethodInvokingMessageSource source = new MethodInvokingMessageSource(); source.setObject(new AtomicInteger()); source.setMethodName("getAndIncrement"); return source; } @Bean public IntegrationFlow controlBusFlow() { return IntegrationFlows.from("controlBus").controlBus().get(); } @Autowired private javax.jms.ConnectionFactory jmsConnectionFactory; @Bean public IntegrationFlow flow1() { return IntegrationFlows .from(this.integerMessageSource(), c -> c.poller(Pollers.fixedRate(100)).id("integerEndpoint").autoStartup(false)) .fixedSubscriberChannel("integerChannel").transform("payload.toString()") .channel(Jms.pollableChannel("flow1QueueChannel", this.jmsConnectionFactory) .destination("flow1QueueChannel")) .get(); } @Bean(name = PollerMetadata.DEFAULT_POLLER) public PollerMetadata poller() { return Pollers.fixedRate(500).maxMessagesPerPoll(1).get(); } @Bean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME) public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.setPoolSize(100); return threadPoolTaskScheduler; } @Bean public MessageChannel inputChannel() { return MessageChannels.direct().get(); } @Bean public MessageChannel foo() { return MessageChannels.publishSubscribe().get(); } @Bean public IntegrationFlow jmsOutboundFlow() { return IntegrationFlows.from("jmsOutboundInboundChannel") .handle(Jms.outboundAdapter(this.jmsConnectionFactory) .destinationExpression("headers." + SimpMessageHeaderAccessor.DESTINATION_HEADER)) .get(); } @Bean public MessageChannel jmsOutboundInboundReplyChannel() { return MessageChannels.queue().get(); } @Bean public IntegrationFlow jmsInboundFlow() { return IntegrationFlows.from(Jms.inboundAdapter(this.jmsConnectionFactory).destination("jmsInbound")) .<String, String>transform(String::toUpperCase).channel(this.jmsOutboundInboundReplyChannel()) .get(); } @Bean public IntegrationFlow jmsMessageDriverFlow() { return IntegrationFlows .from(Jms.messageDriverAdapter(this.jmsConnectionFactory).destination("jmsMessageDriver")) .<String, String>transform(String::toLowerCase).channel(this.jmsOutboundInboundReplyChannel()) .get(); } @Bean public IntegrationFlow jmsOutboundGatewayFlow() { return IntegrationFlows.from("jmsOutboundGatewayChannel") .handle(Jms.outboundGateway(this.jmsConnectionFactory).replyContainer() .requestDestination("jmsPipelineTest")) .get(); } @Bean public IntegrationFlow jmsInboundGatewayFlow() { return IntegrationFlows .from(Jms.inboundGateway(this.jmsConnectionFactory).destination("jmsPipelineTest")) .<String, String>transform(String::toUpperCase).get(); } @Autowired private TestFtpServer ftpServer; @Autowired private DefaultFtpSessionFactory ftpSessionFactory; @Autowired private TestSftpServer sftpServer; @Autowired private DefaultSftpSessionFactory sftpSessionFactory; @Bean public IntegrationFlow ftpInboundFlow() { return IntegrationFlows.from( Ftp.inboundAdapter(this.ftpSessionFactory).preserveTimestamp(true).remoteDirectory("ftpSource") .regexFilter(".*\\.txt$").localFilenameGeneratorExpression("#this.toUpperCase() + '.a'") .localDirectory(this.ftpServer.getTargetLocalDirectory()), e -> e.id("ftpInboundAdapter")).channel(MessageChannels.queue("ftpInboundResultChannel")).get(); } @Bean public IntegrationFlow sftpInboundFlow() { return IntegrationFlows .from(Sftp.inboundAdapter(this.sftpSessionFactory).preserveTimestamp(true) .remoteDirectory("sftpSource").regexFilter(".*\\.txt$") .localFilenameGeneratorExpression("#this.toUpperCase() + '.a'").localDirectory( this.sftpServer.getTargetLocalDirectory()), e -> e.id("sftpInboundAdapter")) .channel(MessageChannels.queue("sftpInboundResultChannel")).get(); } @Bean public IntegrationFlow ftpOutboundFlow() { return IntegrationFlows.from("toFtpChannel").handle(Ftp.outboundAdapter(this.ftpSessionFactory) .useTemporaryFileName(false).remoteDirectory(this.ftpServer.getTargetFtpDirectory().getName())) .get(); } @Bean public IntegrationFlow sftpOutboundFlow() { return IntegrationFlows.from("toSftpChannel") .handle(Sftp.outboundAdapter(this.sftpSessionFactory).useTemporaryFileName(false) .remoteDirectory(this.sftpServer.getTargetSftpDirectory().getName())) .get(); } @Bean public PollableChannel remoteFileOutputChannel() { return new QueueChannel(); } @Bean public IntegrationFlow ftpMGetFlow() { return IntegrationFlows.from("ftpMgetInputChannel").handle(Ftp .outboundGateway(this.ftpSessionFactory, AbstractRemoteFileOutboundGateway.Command.MGET, "payload") .options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE) .regexFileNameFilter("(subFtpSource|.*1.txt)") .localDirectoryExpression("@ftpServer.targetLocalDirectoryName + #remoteDirectory") .localFilenameGeneratorExpression("#remoteFileName.replaceFirst('ftpSource', 'localTarget')")) .channel(remoteFileOutputChannel()).get(); } @Bean public IntegrationFlow sftpMGetFlow() { return IntegrationFlows.from("sftpMgetInputChannel").handle(Sftp .outboundGateway(this.sftpSessionFactory, AbstractRemoteFileOutboundGateway.Command.MGET, "payload") .options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE) .regexFileNameFilter("(subSftpSource|.*1.txt)") .localDirectoryExpression("@sftpServer.targetLocalDirectoryName + #remoteDirectory") .localFilenameGeneratorExpression("#remoteFileName.replaceFirst('sftpSource', 'localTarget')")) .channel(remoteFileOutputChannel()).get(); } } @Configuration @ComponentScan public static class ContextConfiguration2 { @Autowired @Qualifier("inputChannel") private MessageChannel inputChannel; @Autowired @Qualifier("successChannel") private PollableChannel successChannel; @Bean public Advice expressionAdvice() { ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(); advice.setOnSuccessExpression("payload"); advice.setSuccessChannel(this.successChannel); return advice; } @Bean public IntegrationFlow flow2() { return IntegrationFlows.from(this.inputChannel).filter(p -> p instanceof String, c -> c.id("filter")) .channel("foo").fixedSubscriberChannel().<String, Integer>transform(Integer::parseInt) .transform(new PayloadSerializingTransformer(), c -> c.autoStartup(false).id("payloadSerializingTransformer")) .channel(MessageChannels.queue(new SimpleMessageStore(), "fooQueue")) .transform(new PayloadDeserializingTransformer()).channel(publishSubscribeChannel()) .transform((Integer p) -> p * 2, c -> c.advice(this.expressionAdvice())).get(); } @Bean public MessageChannel publishSubscribeChannel() { return MessageChannels.publishSubscribe().get(); } @Bean public MongoDbFactory mongoDbFactory() throws Exception { return new SimpleMongoDbFactory(new MongoClient("localhost", mongoPort), "local"); } @Bean public MongoDbChannelMessageStore mongoDbChannelMessageStore(MongoDbFactory mongoDbFactory) { MongoDbChannelMessageStore mongoDbChannelMessageStore = new MongoDbChannelMessageStore(mongoDbFactory); mongoDbChannelMessageStore.setPriorityEnabled(true); return mongoDbChannelMessageStore; } @Bean public IntegrationFlow priorityFlow(PriorityCapableChannelMessageStore mongoDbChannelMessageStore) { return IntegrationFlows .from(MessageChannels.priority("priorityChannel", mongoDbChannelMessageStore, "priorityGroup")) .bridge(s -> s.poller(Pollers.fixedDelay(100)).autoStartup(false).id("priorityChannelBridge")) .channel(MessageChannels.queue("priorityReplyChannel")).get(); } } @MessageEndpoint public static class AnnotationTestService { @ServiceActivator(inputChannel = "publishSubscribeChannel") public void handle(Object payload) { assertEquals(100, payload); } } @Configuration public static class ContextConfiguration3 { @Autowired @Qualifier("delayedAdvice") private MethodInterceptor delayedAdvice; @Bean public QueueChannel successChannel() { return MessageChannels.queue().get(); } @Bean public AtomicReference<Object> eventHolder() { return new AtomicReference<>(); } @Bean public ApplicationListener<MessagingEvent> eventListener() { return new ApplicationListener<MessagingEvent>() { @Override public void onApplicationEvent(MessagingEvent event) { eventHolder().set(event.getMessage().getPayload()); } }; } @Bean public IntegrationFlow flow3() { return IntegrationFlows.from("flow3Input").handle(Integer.class, (p, h) -> p * 2) .handle(new ApplicationEventPublishingMessageHandler()).get(); } @Bean public IntegrationFlow bridgeFlow() { return IntegrationFlows.from(MessageChannels.queue("bridgeFlowInput")) .channel(MessageChannels.queue("bridgeFlowOutput")).get(); } @Bean public IntegrationFlow bridgeFlow2() { return IntegrationFlows.from("bridgeFlow2Input").bridge(c -> c.autoStartup(false).id("bridge")) .fixedSubscriberChannel() .delay("delayer", "200", c -> c.advice(this.delayedAdvice).messageStore(this.messageStore())) .channel(MessageChannels.queue("bridgeFlow2Output")).get(); } @Bean public SimpleMessageStore messageStore() { return new SimpleMessageStore(); } @Bean public IntegrationFlow claimCheckFlow() { return IntegrationFlows.from("claimCheckInput").claimCheckIn(this.messageStore()) .claimCheckOut(this.messageStore()).get(); } @Bean(name = "foo-channel") public MessageChannel fooChannel() { return new QueueChannel(); } @Bean(name = "bar-channel") public MessageChannel barChannel() { return new QueueChannel(); } @Bean public MessageChannel defaultOutputChannel() { return new QueueChannel(); } @Bean public IntegrationFlow recipientListFlow() { return IntegrationFlows .from("recipientListInput").<String, String>transform( p -> p.replaceFirst("Payload", "")) .recipientListRoute(r -> r.defaultOutputChannel(this.defaultOutputChannel()) .recipient("foo-channel", "'foo' == payload") .recipient("bar-channel", m -> m.getHeaders().containsKey("recipient") && (boolean) m.getHeaders().get("recipient"))) .get(); } } @Component("delayedAdvice") public static class DelayedAdvice implements MethodInterceptor { private final AtomicBoolean invoked = new AtomicBoolean(); @Override public Object invoke(MethodInvocation invocation) throws Throwable { this.invoked.set(true); return invocation.proceed(); } public Boolean getInvoked() { return invoked.get(); } } @Configuration public static class ContextConfiguration4 { @Bean public IntegrationFlow fileFlow1() { return IntegrationFlows.from("fileFlow1Input") .handle(File.outboundAdapter(tmpDir).fileNameGenerator(message -> null), c -> c.id("fileWriting")) .get(); } @Autowired @Qualifier("integrationFlowTests.GreetingService") private MessageHandler greetingService; @Bean public IntegrationFlow methodInvokingFlow() { return IntegrationFlows.from("methodInvokingInput").handle(this.greetingService).get(); } @Bean public IntegrationFlow lamdasFlow() { return IntegrationFlows.from("lamdasInput").filter("World"::equals).transform("Hello "::concat).get(); } @Bean @DependsOn("enrichFlow") public IntegrationFlow enricherFlow() { return IntegrationFlows.fromFixedMessageChannel("enricherInput") .enrich(e -> e.requestChannel("enrichChannel").requestPayloadExpression("payload") .shouldClonePayload(false).propertyExpression("name", "payload['name']") .propertyExpression("date", "new java.util.Date()") .headerExpression("foo", "payload['name']")) .get(); } @Bean @DependsOn("enrichFlow") public IntegrationFlow enricherFlow2() { return IntegrationFlows.fromFixedMessageChannel("enricherInput2") .enrich(e -> e.requestChannel("enrichChannel").requestPayloadExpression("payload") .shouldClonePayload(false).propertyExpression("name", "payload['name']") .propertyExpression("date", "new java.util.Date()")) .get(); } @Bean @DependsOn("enrichFlow") public IntegrationFlow enricherFlow3() { return IntegrationFlows.fromFixedMessageChannel("enricherInput3") .enrich(e -> e.requestChannel("enrichChannel").requestPayloadExpression("payload") .shouldClonePayload(false).headerExpression("foo", "payload['name']")) .get(); } @Bean public IntegrationFlow enrichFlow() { return IntegrationFlows.from("enrichChannel") .<TestPojo, Map<?, ?>>transform(p -> Collections.singletonMap("name", p.getName() + " Bar")) .get(); } @Bean public Executor taskExecutor() { return Executors.newCachedThreadPool(); } @Bean public TestSplitterPojo testSplitterData() { List<String> first = new ArrayList<>(); first.add("1,2,3"); first.add("4,5,6"); List<String> second = new ArrayList<>(); second.add("7,8,9"); second.add("10,11,12"); return new TestSplitterPojo(first, second); } @Bean public IntegrationFlow splitResequenceFlow() { return IntegrationFlows.from("splitInput").enrichHeaders(s -> s.header("FOO", "BAR")) .split("testSplitterData", "buildList", c -> c.applySequence(false)) .channel(MessageChannels.executor(this.taskExecutor())) .split(Message.class, target -> (List<?>) target.getPayload(), c -> c.applySequence(false)) .channel(MessageChannels.executor(this.taskExecutor())) .split(s -> s.applySequence(false).get().getT2().setDelimiters(",")) .channel(MessageChannels.executor(this.taskExecutor())) .<String, Integer>transform(Integer::parseInt) .enrichHeaders( s -> s.headerExpression(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER, "payload")) .resequence(r -> r.releasePartialSequences(true).correlationExpression("'foo'"), null) .headerFilter("foo", false).get(); } @Bean public IntegrationFlow splitAggregateFlow() { return IntegrationFlows.fromFixedMessageChannel("splitAggregateInput").split(null) .channel(MessageChannels.executor(this.taskExecutor())).resequence().aggregate().get(); } @Bean public IntegrationFlow xpathHeaderEnricherFlow() { return IntegrationFlows.from("xpathHeaderEnricherInput").enrichHeaders(s -> s .header("one", new XPathExpressionEvaluatingHeaderValueMessageProcessor("/root/elementOne")) .header("two", new XPathExpressionEvaluatingHeaderValueMessageProcessor("/root/elementTwo")) .headerChannelsToString(), c -> c.autoStartup(false).id("xpathHeaderEnricher")).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") .route(String.class, p -> p.equals("foo") || p.equals("bar") ? new String[] { "foo", "bar" } : null, s -> s.suffix("-channel")) .get(); } @Bean public IntegrationFlow tailFlow() { return IntegrationFlows .from(File.tailAdapter(new java.io.File(tmpDir, "TailTest")).delay(500).id("tailer")) .transform("hello "::concat).channel(MessageChannels.queue("tailChannel")).get(); } @Autowired private ConnectionFactory rabbitConnectionFactory; @Autowired private AmqpTemplate amqpTemplate; @Bean public Queue queue() { return new AnonymousQueue(); } @Bean public IntegrationFlow amqpFlow() { return IntegrationFlows.from(Amqp.inboundGateway(this.rabbitConnectionFactory, queue())) .transform("hello "::concat).transform(String.class, String::toUpperCase).get(); } @Bean public IntegrationFlow amqpOutboundFlow() { return IntegrationFlows.from(Amqp.channel("amqpOutboundInput", this.rabbitConnectionFactory)) .handle(Amqp.outboundAdapter(this.amqpTemplate).routingKeyExpression("headers.routingKey")) .get(); } @Bean public Queue fooQueue() { return new Queue("foo"); } @Bean public Queue amqpReplyChannel() { return new Queue("amqpReplyChannel"); } @Bean public IntegrationFlow amqpInboundFlow() { return IntegrationFlows.from(Amqp.inboundAdapter(this.rabbitConnectionFactory, fooQueue())) .transform(String.class, String::toUpperCase) .channel(Amqp.pollableChannel(this.rabbitConnectionFactory).queueName("amqpReplyChannel") .channelTransacted(true)) .get(); } @Bean @DependsOn("gatewayRequestFlow") public IntegrationFlow gatewayFlow() { return IntegrationFlows.from("gatewayInput") .gateway("gatewayRequest", g -> g.errorChannel("gatewayError").replyTimeout(10L)).get(); } @Bean public IntegrationFlow gatewayRequestFlow() { return IntegrationFlows.from("gatewayRequest") .filter("foo"::equals, f -> f.throwExceptionOnRejection(true)) .<String, String>transform(String::toUpperCase).get(); } @Bean public MessageChannel gatewayError() { return MessageChannels.queue().get(); } @Bean public IntegrationFlow fileReadingFlow() { return IntegrationFlows .from(File.inboundAdapter(tmpDir).patternFilter("*.sitest"), e -> e.poller(Pollers.fixedDelay(100))) .transform(Transformers.fileToString()) .aggregate(a -> a.correlationExpression("1").releaseExpression("size() == 25"), null) .channel(MessageChannels.queue("fileReadingResultChannel")).get(); } @Bean public IntegrationFlow fileWritingFlow() { return IntegrationFlows.from("fileWritingInput") .enrichHeaders(h -> h.header(FileHeaders.FILENAME, "foo.sitest").header("directory", new java.io.File(tmpDir, "fileWritingFlow"))) .handle(File.outboundGateway("headers[directory]")) .channel(MessageChannels.queue("fileWritingResultChannel")).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; } } @Service public static class GreetingService extends AbstractReplyProducingMessageHandler { @Autowired private WorldService worldService; @Override protected Object handleRequestMessage(Message<?> requestMessage) { return "Hello " + this.worldService.world() + " and " + requestMessage.getPayload(); } } @Service public static class WorldService { public String world() { return "World"; } } private static class InvalidLastComponentFlowContext { @Bean public IntegrationFlow wrongLastComponent() { return IntegrationFlows.from(MessageChannels.direct()).route(Object::toString) .channel(MessageChannels.direct()).get(); } } private static class InvalidLastMessageChannelFlowContext { @Bean public IntegrationFlow wrongLastComponent() { return IntegrationFlows.from(MessageChannels.direct()).fixedSubscriberChannel().get(); } } @EnableIntegration public static class InvalidConfigurationWithSpec { @Bean public DirectChannelSpec invalidBean() { return MessageChannels.direct(); } } @Component @GlobalChannelInterceptor(patterns = "flow1QueueChannel") public static class TestChannelInterceptor extends ChannelInterceptorAdapter { private final AtomicInteger invoked = new AtomicInteger(); @Override public Message<?> preSend(Message<?> message, MessageChannel channel) { this.invoked.incrementAndGet(); return message; } public Integer getInvoked() { return invoked.get(); } } private static class TestPojo { private String name; private Date date; private TestPojo(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } } private static class TestSplitterPojo { final List<String> first; final List<String> second; private TestSplitterPojo(List<String> first, List<String> second) { this.first = first; this.second = second; } public List<String> getFirst() { return first; } public List<String> getSecond() { return second; } public List<List<String>> buildList() { return Arrays.asList(this.first, this.second); } } }