/* * Copyright 2002-2016 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.router; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.core.MessageSelector; import org.springframework.integration.router.RecipientListRouter.Recipient; import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.support.GenericMessage; /** * @author Mark Fisher * @author Gary Russell * @author Artem Bilan */ public class RecipientListRouterTests { @Test @SuppressWarnings("unchecked") public void channelConfig() { QueueChannel channel1 = new QueueChannel(); QueueChannel channel2 = new QueueChannel(); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channel1); channels.add(channel2); RecipientListRouter router = new RecipientListRouter(); router.setChannels(channels); router.setBeanFactory(mock(BeanFactory.class)); router.afterPropertiesSet(); ConcurrentLinkedQueue<Recipient> recipients = (ConcurrentLinkedQueue<Recipient>) new DirectFieldAccessor(router).getPropertyValue("recipients"); assertEquals(2, recipients.size()); assertEquals(channel1, new DirectFieldAccessor(recipients.poll()).getPropertyValue("channel")); assertEquals(channel2, new DirectFieldAccessor(recipients.poll()).getPropertyValue("channel")); } @Test public void routeWithChannelList() { QueueChannel channel1 = new QueueChannel(); QueueChannel channel2 = new QueueChannel(); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channel1); channels.add(channel2); RecipientListRouter router = new RecipientListRouter(); router.setChannels(channels); router.setBeanFactory(mock(BeanFactory.class)); router.afterPropertiesSet(); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1 = channel1.receive(25); assertNotNull(result1); assertEquals("test", result1.getPayload()); Message<?> result2 = channel2.receive(25); assertNotNull(result2); assertEquals("test", result2.getPayload()); } @Test public void routeToSingleChannel() { QueueChannel channel = new QueueChannel(); channel.setBeanName("channel"); RecipientListRouter router = new RecipientListRouter(); router.setChannels(Collections.singletonList((MessageChannel) channel)); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1 = channel.receive(25); assertNotNull(result1); assertEquals("test", result1.getPayload()); Message<?> result2 = channel.receive(5); assertNull(result2); } @Test(expected = MessageDeliveryException.class) public void sendFailureOnFirstRecipientTriggersExceptionByDefault() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); QueueChannel channelC = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); channelC.setBeanName("channelC"); RecipientListRouter router = new RecipientListRouter(); router.setSendTimeout(0); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); channels.add(channelC); router.setChannels(channels); channelA.send(new GenericMessage<String>("blocker")); Message<String> message = new GenericMessage<String>("test"); try { router.handleMessage(message); } catch (RuntimeException e) { Message<?> result1a = channelA.receive(0); assertNotNull(result1a); assertEquals("blocker", result1a.getPayload()); assertNull(channelB.receive(0)); assertNull(channelC.receive(0)); throw e; } } @Test(expected = MessageDeliveryException.class) public void sendFailureOnMiddleRecipientTriggersExceptionByDefault() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); QueueChannel channelC = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); channelC.setBeanName("channelC"); RecipientListRouter router = new RecipientListRouter(); router.setSendTimeout(0); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); channels.add(channelC); router.setChannels(channels); channelB.send(new GenericMessage<String>("blocker")); Message<String> message = new GenericMessage<String>("test"); try { router.handleMessage(message); } catch (RuntimeException e) { Message<?> result1a = channelA.receive(0); assertNotNull(result1a); assertEquals("test", result1a.getPayload()); Message<?> result1b = channelB.receive(0); assertNotNull(result1b); assertEquals("blocker", result1b.getPayload()); assertNull(channelC.receive(0)); throw e; } } @Test(expected = MessageDeliveryException.class) public void sendFailureOnLastRecipientTriggersExceptionByDefault() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); QueueChannel channelC = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); channelC.setBeanName("channelC"); RecipientListRouter router = new RecipientListRouter(); router.setSendTimeout(0); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); channels.add(channelC); router.setChannels(channels); channelC.send(new GenericMessage<String>("blocker")); Message<String> message = new GenericMessage<String>("test"); try { router.handleMessage(message); } catch (RuntimeException e) { Message<?> result1a = channelA.receive(0); assertNotNull(result1a); assertEquals("test", result1a.getPayload()); Message<?> result1b = channelB.receive(0); assertNotNull(result1b); assertEquals("test", result1b.getPayload()); Message<?> result1c = channelC.receive(0); assertNotNull(result1c); assertEquals("blocker", result1c.getPayload()); throw e; } } @Test public void sendFailureOnFirstRecipientIgnored() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); QueueChannel channelC = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); channelC.setBeanName("channelC"); RecipientListRouter router = new RecipientListRouter(); router.setIgnoreSendFailures(true); router.setSendTimeout(0); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); channels.add(channelC); router.setChannels(channels); channelA.send(new GenericMessage<String>("blocker")); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1a = channelA.receive(0); Message<?> result1b = channelB.receive(0); Message<?> result1c = channelC.receive(0); assertNotNull(result1a); assertNotNull(result1b); assertNotNull(result1c); assertEquals("blocker", result1a.getPayload()); assertEquals("test", result1b.getPayload()); assertEquals("test", result1c.getPayload()); } @Test public void sendFailureOnMiddleRecipientIgnored() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); QueueChannel channelC = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); channelC.setBeanName("channelC"); RecipientListRouter router = new RecipientListRouter(); router.setIgnoreSendFailures(true); router.setSendTimeout(0); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); channels.add(channelC); router.setChannels(channels); channelB.send(new GenericMessage<String>("blocker")); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1a = channelA.receive(0); Message<?> result1b = channelB.receive(0); Message<?> result1c = channelC.receive(0); assertNotNull(result1a); assertNotNull(result1b); assertNotNull(result1c); assertEquals("test", result1a.getPayload()); assertEquals("blocker", result1b.getPayload()); assertEquals("test", result1c.getPayload()); } @Test public void sendFailureOnLastRecipientIgnored() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); QueueChannel channelC = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); channelC.setBeanName("channelC"); RecipientListRouter router = new RecipientListRouter(); router.setIgnoreSendFailures(true); router.setSendTimeout(0); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); channels.add(channelC); router.setChannels(channels); channelC.send(new GenericMessage<String>("blocker")); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1a = channelA.receive(0); Message<?> result1b = channelB.receive(0); Message<?> result1c = channelC.receive(0); assertNotNull(result1a); assertNotNull(result1b); assertNotNull(result1c); assertEquals("test", result1a.getPayload()); assertEquals("test", result1b.getPayload()); assertEquals("blocker", result1c.getPayload()); } @Test public void applySequenceNotEnabledByDefault() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); RecipientListRouter router = new RecipientListRouter(); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); router.setChannels(channels); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1a = channelA.receive(0); Message<?> result1b = channelB.receive(0); assertNotNull(result1a); assertNotNull(result1b); assertEquals("test", result1a.getPayload()); assertEquals(0, new IntegrationMessageHeaderAccessor(result1a).getSequenceNumber().intValue()); assertEquals(0, new IntegrationMessageHeaderAccessor(result1a).getSequenceSize().intValue()); assertNull(new IntegrationMessageHeaderAccessor(result1a).getCorrelationId()); assertEquals("test", result1b.getPayload()); assertEquals(0, new IntegrationMessageHeaderAccessor(result1b).getSequenceNumber().intValue()); assertEquals(0, new IntegrationMessageHeaderAccessor(result1b).getSequenceSize().intValue()); assertNull(new IntegrationMessageHeaderAccessor(result1b).getCorrelationId()); } @Test public void applySequenceEnabled() { QueueChannel channelA = new QueueChannel(1); QueueChannel channelB = new QueueChannel(1); channelA.setBeanName("channelA"); channelB.setBeanName("channelB"); RecipientListRouter router = new RecipientListRouter(); router.setApplySequence(true); List<MessageChannel> channels = new ArrayList<MessageChannel>(); channels.add(channelA); channels.add(channelB); router.setChannels(channels); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1a = channelA.receive(0); Message<?> result1b = channelB.receive(0); assertNotNull(result1a); assertNotNull(result1b); assertEquals("test", result1a.getPayload()); assertEquals(1, new IntegrationMessageHeaderAccessor(result1a).getSequenceNumber().intValue()); assertEquals(2, new IntegrationMessageHeaderAccessor(result1a).getSequenceSize().intValue()); assertEquals(message.getHeaders().getId(), new IntegrationMessageHeaderAccessor(result1a).getCorrelationId()); assertEquals("test", result1b.getPayload()); assertEquals(2, new IntegrationMessageHeaderAccessor(result1b).getSequenceNumber().intValue()); assertEquals(2, new IntegrationMessageHeaderAccessor(result1b).getSequenceSize().intValue()); assertEquals(message.getHeaders().getId(), new IntegrationMessageHeaderAccessor(result1b).getCorrelationId()); } @Test(expected = IllegalArgumentException.class) public void nullChannelListRejected() { RecipientListRouter router = new RecipientListRouter(); router.setChannels(null); } @Test(expected = IllegalArgumentException.class) public void emptyChannelListRejected() { RecipientListRouter router = new RecipientListRouter(); List<MessageChannel> channels = new ArrayList<MessageChannel>(); router.setChannels(channels); } @Test public void noChannelListPassInitialization() { RecipientListRouter router = new RecipientListRouter(); router.setBeanFactory(mock(BeanFactory.class)); QueueChannel defaultOutputChannel = new QueueChannel(); router.setDefaultOutputChannel(defaultOutputChannel); router.afterPropertiesSet(); router.handleMessage(new GenericMessage<String>("foo")); Message<?> receive = defaultOutputChannel.receive(1000); assertNotNull(receive); } @Test public void recipientsWithSelectors() { QueueChannel channel1 = new QueueChannel(); QueueChannel channel2 = new QueueChannel(); QueueChannel channel3 = new QueueChannel(); QueueChannel channel4 = new QueueChannel(); QueueChannel channel5 = new QueueChannel(); List<Recipient> recipients = new ArrayList<Recipient>(); recipients.add(new Recipient(channel1, new AlwaysTrueSelector())); recipients.add(new Recipient(channel2, new AlwaysFalseSelector())); recipients.add(new Recipient(channel3)); recipients.add(new Recipient(channel4)); recipients.add(new Recipient(channel5, new AlwaysFalseSelector())); RecipientListRouter router = new RecipientListRouter(); router.setRecipients(recipients); Message<?> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> reply1 = channel1.receive(0); assertEquals(message, reply1); Message<?> reply2 = channel2.receive(0); assertNull(reply2); Message<?> reply3 = channel3.receive(0); assertEquals(message, reply3); Message<?> reply4 = channel4.receive(0); assertEquals(message, reply4); Message<?> reply5 = channel5.receive(0); assertNull(reply5); } @Test public void routeToDefaultChannelNoSelectorHits() { QueueChannel channel = new QueueChannel(); channel.setBeanName("channel"); QueueChannel defaultChannel = new QueueChannel(); channel.setBeanName("default"); List<Recipient> recipients = new ArrayList<Recipient>(); recipients.add(new Recipient(channel, new AlwaysFalseSelector())); RecipientListRouter router = new RecipientListRouter(); router.setRecipients(recipients); router.setDefaultOutputChannel(defaultChannel); Message<String> message = new GenericMessage<String>("test"); router.handleMessage(message); Message<?> result1 = defaultChannel.receive(25); assertNotNull(result1); assertEquals("test", result1.getPayload()); Message<?> result2 = channel.receive(5); assertNull(result2); } @Test public void testDefaultChannelResolutionFromName() { QueueChannel defaultChannel = new QueueChannel(); List<Recipient> recipients = new ArrayList<Recipient>(); recipients.add(new Recipient(new DirectChannel(), new AlwaysFalseSelector())); RecipientListRouter router = new RecipientListRouter(); router.setRecipients(recipients); router.setDefaultOutputChannelName("defaultChannel"); BeanFactory beanFactory = Mockito.mock(BeanFactory.class); when(beanFactory.getBean(Mockito.eq("defaultChannel"), Mockito.eq(MessageChannel.class))) .thenReturn(defaultChannel); router.setBeanFactory(beanFactory); router.afterPropertiesSet(); router.handleMessage(new GenericMessage<String>("foo")); assertSame(defaultChannel, TestUtils.getPropertyValue(router, "defaultOutputChannel")); Mockito.verify(beanFactory).getBean(Mockito.eq("defaultChannel"), Mockito.eq(MessageChannel.class)); } private static class AlwaysTrueSelector implements MessageSelector { AlwaysTrueSelector() { super(); } @Override public boolean accept(Message<?> message) { return true; } } private static class AlwaysFalseSelector implements MessageSelector { AlwaysFalseSelector() { super(); } @Override public boolean accept(Message<?> message) { return false; } } }