diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.2.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.2.xsd index 8a69102be4..67c52bd5cc 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.2.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.2.xsd @@ -34,24 +34,24 @@ - + Allows you to configure org.springframework.integration.transaction.DefaultTransactionSynchronizationFactory This implementation of org.springframework.integration.transaction.TransactionSynchronizationFactory - allows you to configure SpEL expressions, with their execution being coordinated (synchronized) with a - transaction - see {TransactionSynchronization}. Expressions for before-commit, after.-commit, and after-rollback + allows you to configure SpEL expressions, with their execution being coordinated (synchronized) with a + transaction - see {TransactionSynchronization}. Expressions for before-commit, after.-commit, and after-rollback are supported, together with a channel for each where the evaluation result (if any) will be sent. For each sub-element you can specify 'expression' and/or 'channel' attributes. If only the 'channel' attribute is present the received Message will be sent there as part of a particular synchronization scenario. - If only the 'expression' attribute is present and the result of an expression is a non-Null value, a Message with the - result as the payload will be generated and sent to a default channel (NullChannel) and will appear in the logs. - If you want the evaluation result to go to a specific channel add a 'channel' attribute. If the result of an expression is null + If only the 'expression' attribute is present and the result of an expression is a non-Null value, a Message with the + result as the payload will be generated and sent to a default channel (NullChannel) and will appear in the logs. + If you want the evaluation result to go to a specific channel add a 'channel' attribute. If the result of an expression is null or void, no Message will be generated. - + @@ -72,7 +72,7 @@ - + @@ -3459,7 +3459,7 @@ is provided, the return value is expected to match a channel name exactly. @@ -3497,7 +3497,7 @@ is provided, the return value is expected to match a channel name exactly. diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd index c97af0bcc9..85a1c0ede0 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd @@ -2555,34 +2555,7 @@ - - - - - - - - - - - - - + @@ -2593,21 +2566,45 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/config/ErrorChannelRoutingTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/router/config/ErrorChannelRoutingTests-context.xml deleted file mode 100644 index b10b252c23..0000000000 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/config/ErrorChannelRoutingTests-context.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/config/routerParserTests.xml b/spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests-context.xml similarity index 80% rename from spring-integration-core/src/test/java/org/springframework/integration/router/config/routerParserTests.xml rename to spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests-context.xml index 805da92b92..6f9e050cab 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/config/routerParserTests.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests-context.xml @@ -1,11 +1,11 @@ - + http://www.springframework.org/schema/integration/spring-integration.xsd"> @@ -68,18 +68,33 @@ - + - + - - + - + + + + + + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests.java index aa13de4f47..03d54fdc8c 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/config/RouterParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2013 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. @@ -19,6 +19,7 @@ package org.springframework.integration.router.config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -27,15 +28,16 @@ import java.util.Collections; import java.util.List; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.MessageDeliveryException; import org.springframework.integration.annotation.Router; -import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.core.PollableChannel; @@ -43,118 +45,149 @@ import org.springframework.integration.core.SubscribableChannel; import org.springframework.integration.message.GenericMessage; import org.springframework.integration.router.AbstractMappingMessageRouter; import org.springframework.integration.router.MethodInvokingRouter; +import org.springframework.integration.support.channel.ChannelResolutionException; import org.springframework.integration.support.channel.ChannelResolver; import org.springframework.integration.test.util.TestUtils; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Mark Fisher * @author Jonas Partner * @author Gunnar Hillert + * @author Artem Bilan */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) public class RouterParserTests { + @Autowired + private PollableChannel output1; + + @Autowired + private PollableChannel output2; + @Autowired + private MessageChannel input; + + @Autowired + private MessageChannel inputForRouterWithDefaultOutput; + + @Autowired + private PollableChannel defaultOutput; + + @Autowired + private MessageChannel inputForAbstractMessageRouterImplementation; + + @Autowired + private PollableChannel output3; + + @Autowired + private MessageChannel inputForAnnotatedRouter; + + @Autowired + private PollableChannel output4; + + @Autowired + private MessageChannel inputForRouterRequiringResolution; + + @Autowired + private MessageChannel resolutionRequiredIsFalseInput; + + @Autowired + @Qualifier("routerWithTimeout.handler") + private MessageHandler routerWithTimeout; + + @Autowired + private MessageChannel sequenceRouter; + + @Autowired + private PollableChannel sequenceOut1; + + @Autowired + private PollableChannel sequenceOut2; + + @Autowired + private PollableChannel sequenceOut3; + + @Autowired + private MessageChannel routerNestedBeanChannel; + + @Autowired + private MessageChannel chainRouterNestedBeanChannel; + + @Autowired + private MessageChannel routerAndErrorChannelInputChannel; + + @Autowired + private SubscribableChannel errorChannel; + @Test public void testRouter() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - context.start(); - MessageChannel input = (MessageChannel) context.getBean("input"); - PollableChannel output1 = (PollableChannel) context.getBean("output1"); - PollableChannel output2 = (PollableChannel) context.getBean("output2"); - input.send(new GenericMessage("1")); - Message result1 = output1.receive(1000); + this.input.send(new GenericMessage("1")); + Message result1 = this.output1.receive(1000); assertEquals("1", result1.getPayload()); assertNull(output2.receive(0)); input.send(new GenericMessage("2")); - Message result2 = output2.receive(1000); + Message result2 = this.output2.receive(1000); assertEquals("2", result2.getPayload()); assertNull(output1.receive(0)); } @Test public void testRouterWithDefaultOutputChannel() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - context.start(); - MessageChannel input = (MessageChannel) context.getBean("inputForRouterWithDefaultOutput"); - PollableChannel output1 = (PollableChannel) context.getBean("output1"); - PollableChannel output2 = (PollableChannel) context.getBean("output2"); - PollableChannel defaultOutput = (PollableChannel) context.getBean("defaultOutput"); - input.send(new GenericMessage("99")); - assertNull(output1.receive(0)); - assertNull(output2.receive(0)); - Message result = defaultOutput.receive(0); + this.inputForRouterWithDefaultOutput.send(new GenericMessage("99")); + assertNull(this.output1.receive(0)); + assertNull(this.output2.receive(0)); + Message result = this.defaultOutput.receive(0); assertEquals("99", result.getPayload()); } @Test public void refOnlyForAbstractMessageRouterImplementation() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - context.start(); - MessageChannel input = (MessageChannel) context.getBean("inputForAbstractMessageRouterImplementation"); - PollableChannel output = (PollableChannel) context.getBean("output3"); - input.send(new GenericMessage("test-implementation")); - Message result = output.receive(0); + this.inputForAbstractMessageRouterImplementation.send(new GenericMessage("test-implementation")); + Message result = this.output3.receive(1000); assertNotNull(result); - assertEquals("test-implementation", result.getPayload()); + assertEquals("test-implementation", result.getPayload()); } @Test public void refOnlyForAnnotatedObject() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - context.start(); - MessageChannel input = (MessageChannel) context.getBean("inputForAnnotatedRouter"); - PollableChannel output = (PollableChannel) context.getBean("output4"); - input.send(new GenericMessage("test-annotation")); - Message result = output.receive(0); + this.inputForAnnotatedRouter.send(new GenericMessage("test-annotation")); + Message result = this.output4.receive(1000); assertNotNull(result); - assertEquals("test-annotation", result.getPayload()); - } - - @Test(expected=MessageDeliveryException.class) - public void testResolutionRequired() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - context.start(); - MessageChannel input = (MessageChannel) context.getBean("inputForRouterRequiringResolution"); - input.send(new GenericMessage(3)); + assertEquals("test-annotation", result.getPayload()); } - public void testResolutionRequiredIsTrue() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - context.start(); - MessageChannel input = (MessageChannel) context.getBean("resolutionRequiredIsTrueInput"); - input.send(new GenericMessage("channelThatDoesNotExist")); + @Test + public void testResolutionRequired() { + try { + this.inputForRouterRequiringResolution.send(new GenericMessage(3)); + } + catch (Exception e) { + assertTrue(e.getCause() instanceof ChannelResolutionException); + } + } + + @Test(expected=MessageDeliveryException.class) + public void testResolutionRequiredIsFalse() { + this.resolutionRequiredIsFalseInput.send(new GenericMessage("channelThatDoesNotExist")); } @Test public void timeoutValueConfigured() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - Object endpoint = context.getBean("routerWithTimeout"); - MethodInvokingRouter router = TestUtils.getPropertyValue(endpoint, "handler", MethodInvokingRouter.class); - MessagingTemplate template = (MessagingTemplate) - new DirectFieldAccessor(router).getPropertyValue("messagingTemplate"); - Long timeout = (Long) new DirectFieldAccessor(template).getPropertyValue("sendTimeout"); + assertTrue(this.routerWithTimeout instanceof MethodInvokingRouter); + MessagingTemplate template = TestUtils.getPropertyValue(this.routerWithTimeout, "messagingTemplate", MessagingTemplate.class); + Long timeout = TestUtils.getPropertyValue(template, "sendTimeout", Long.class); assertEquals(new Long(1234), timeout); } @Test public void sequence() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "routerParserTests.xml", this.getClass()); - MessageChannel input = context.getBean("sequenceRouter", MessageChannel.class); - PollableChannel out1 = context.getBean("sequenceOut1", PollableChannel.class); - PollableChannel out2 = context.getBean("sequenceOut2", PollableChannel.class); - PollableChannel out3 = context.getBean("sequenceOut3", PollableChannel.class); Message originalMessage = new GenericMessage("test"); - input.send(originalMessage); - Message message1 = out1.receive(0); - Message message2 = out2.receive(0); - Message message3 = out3.receive(0); + this.sequenceRouter.send(originalMessage); + Message message1 = this.sequenceOut1.receive(1000); + Message message2 = this.sequenceOut2.receive(1000); + Message message3 = this.sequenceOut3.receive(1000); assertEquals(originalMessage.getHeaders().getId(), message1.getHeaders().getCorrelationId()); assertEquals(originalMessage.getHeaders().getId(), message2.getHeaders().getCorrelationId()); assertEquals(originalMessage.getHeaders().getId(), message3.getHeaders().getCorrelationId()); @@ -166,23 +199,44 @@ public class RouterParserTests { assertEquals(new Integer(3), message3.getHeaders().getSequenceSize()); } + @Test + public void testInt2893RouterNestedBean() { + this.routerNestedBeanChannel.send(new GenericMessage("1")); + Message result1 = this.output1.receive(1000); + assertEquals("1", result1.getPayload()); + assertNull(this.output2.receive(0)); + this.routerNestedBeanChannel.send(new GenericMessage("2")); + Message result2 = this.output2.receive(1000); + assertEquals("2", result2.getPayload()); + assertNull(this.output1.receive(0)); + } + + @Test + public void testInt2893RouterNestedBeanWithinChain() { + this.chainRouterNestedBeanChannel.send(new GenericMessage("1")); + Message result1 = this.output1.receive(1000); + assertEquals("1", result1.getPayload()); + assertNull(this.output2.receive(0)); + this.chainRouterNestedBeanChannel.send(new GenericMessage("2")); + Message result2 = this.output2.receive(1000); + assertEquals("2", result2.getPayload()); + assertNull(this.output1.receive(0)); + } + @Test public void testErrorChannel(){ - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "ErrorChannelRoutingTests-context.xml", this.getClass()); MessageHandler handler = mock(MessageHandler.class); - DirectChannel inputChannel = context.getBean("inputChannel", DirectChannel.class); - SubscribableChannel errorChannel = context.getBean("errorChannel", SubscribableChannel.class); - errorChannel.subscribe(handler); - inputChannel.send(new GenericMessage("fail")); + this.errorChannel.subscribe(handler); + this.routerAndErrorChannelInputChannel.send(new GenericMessage("fail")); verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); } - + @Test // should not fail public void routerFactoryBeanTest(){ new ClassPathXmlApplicationContext("rfb-fix-config.xml", this.getClass()); } - + + public static class NonExistingChannelRouter{ public String route(String payload){ return "foo"; @@ -218,7 +272,7 @@ public class RouterParserTests { return this.channel; } } - + public static class ReturnStringPassedInAsChannelNameRouter { @Router @@ -226,7 +280,7 @@ public class RouterParserTests { return (String)message.getPayload(); } - + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/config/TestRouter.java b/spring-integration-core/src/test/java/org/springframework/integration/router/config/TestRouter.java index 21f5ead1c0..b9309e8db2 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/config/TestRouter.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/config/TestRouter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2013 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. @@ -28,6 +28,9 @@ public class TestRouter { if (input == 2) { return "output2"; } + if (input == 3) { + return "channelDoesNotExist"; + } return null; } diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests-context.xml b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests-context.xml index 266178ab63..a52c7b62f7 100644 --- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests-context.xml +++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests-context.xml @@ -23,10 +23,21 @@ 5 ? "longStrings" : "shortStrings"; - })(); + (function(){ + return payload.length > 5 ? "longStrings" : "shortStrings"; + })(); ]]> + + + 5 ? "longStrings" : "shortStrings"; + })(); + ]]> + + + + diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests.java b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests.java index 24bcec2191..92d9eec296 100644 --- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests.java +++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223RouterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2013 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. @@ -33,6 +33,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Mark Fisher * @author David Turanski + * @author Artem Bilan * @since 2.1 */ @ContextConfiguration @@ -45,6 +46,9 @@ public class Jsr223RouterTests { @Autowired private MessageChannel inlineScriptInput; + @Autowired + private MessageChannel scriptRouterWithinChainInput; + @Autowired private PollableChannel longStrings; @@ -94,4 +98,25 @@ public class Jsr223RouterTests { assertNull(longStrings.receive(0)); } + @Test + public void testInt2893ScriptRouterWithinChain() { + Message message1 = new GenericMessage("aardvark"); + Message message2 = new GenericMessage("bear"); + Message message3 = new GenericMessage("cat"); + Message message4 = new GenericMessage("dog"); + Message message5 = new GenericMessage("elephant"); + this.scriptRouterWithinChainInput.send(message1); + this.scriptRouterWithinChainInput.send(message2); + this.scriptRouterWithinChainInput.send(message3); + this.scriptRouterWithinChainInput.send(message4); + this.scriptRouterWithinChainInput.send(message5); + assertEquals("bear", shortStrings.receive(0).getPayload()); + assertEquals("cat", shortStrings.receive(0).getPayload()); + assertEquals("dog", shortStrings.receive(0).getPayload()); + assertEquals("aardvark", longStrings.receive(0).getPayload()); + assertEquals("elephant", longStrings.receive(0).getPayload()); + assertNull(shortStrings.receive(0)); + assertNull(longStrings.receive(0)); + } + }