diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java index f4532f9abd..cec647029f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java @@ -39,6 +39,8 @@ public class SplitterFactoryBean extends AbstractStandardMessageHandlerFactoryBe private volatile boolean applySequence = true; + private volatile String delimiters; + public void setSendTimeout(Long sendTimeout) { this.sendTimeout = sendTimeout; @@ -56,6 +58,10 @@ public class SplitterFactoryBean extends AbstractStandardMessageHandlerFactoryBe this.applySequence = applySequence; } + public void setDelimiters(String delimiters) { + this.delimiters = delimiters; + } + @Override MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) { Assert.notNull(targetObject, "targetObject must not be null"); @@ -95,6 +101,11 @@ public class SplitterFactoryBean extends AbstractStandardMessageHandlerFactoryBe if (this.sendTimeout != null) { splitter.setSendTimeout(sendTimeout); } + if (this.delimiters != null) { + Assert.isTrue(splitter instanceof DefaultMessageSplitter, "The 'delimiters' property is only available" + + " for a Splitter definition where no 'ref', 'expression', or inner bean has been provided."); + ((DefaultMessageSplitter) splitter).setDelimiters(this.delimiters); + } splitter.setRequiresReply(requiresReply); splitter.setApplySequence(applySequence); return splitter; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/SplitterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/SplitterParser.java index 95e7530367..61c30902e9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/SplitterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/SplitterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 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. @@ -41,5 +41,7 @@ public class SplitterParser extends AbstractDelegatingConsumerEndpointParser { @Override void postProcess(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) { IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "apply-sequence"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "delimiters"); } + } diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd index 045f72526d..c63b671cfd 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd @@ -1088,24 +1088,7 @@ endpoint itself is a Polling Consumer for a channel with a queue. - - - - - - - - Set this flag to false to prevent adding sequence related headers in this splitter. This - can be - convenient in cases where the set sequence numbers conflict with downstream custom - aggregations. - - - - - - - + @@ -2356,34 +2339,48 @@ Name of the header whose value will be used to route messages - + - - - - Specify whether the splitter method must return a non-null value. This value will be - FALSE by - default, but if set to TRUE, a MessageHandlingException will be thrown when - the underlying service method (or - expression) returns a NULL value. - - - - - - - Set this flag to false to prevent adding sequence related headers in this splitter. This - can be - convenient in cases where the set sequence numbers conflict with downstream custom - aggregations. - - - + + + + + + + Specify whether the splitter method must return a non-null value. This value will be + FALSE by default, but if set to TRUE, a MessageHandlingException will be thrown when + the underlying service method (or expression) returns a NULL value. + + + + + + + Set this flag to false to prevent adding sequence related headers in this splitter. + This can be convenient in cases where the set sequence numbers conflict with downstream + custom aggregations. + + + + + + + Provide one or more delimiters (as a single String value, e.g. delimiters=",;:") for + tokenizing String-typed payload values. This attribute is only allowed if no 'ref' or + 'expression' have been provided since that is when the DefaultMessageSplitter would + be used, and it's the implementation that contains the "delimiters" property. + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-context.xml index 52f0660aae..7f8fb3baf2 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-context.xml @@ -19,13 +19,14 @@ + + - + \ No newline at end of file diff --git a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidExpression.xml b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidExpression.xml new file mode 100644 index 0000000000..3cc8e2a859 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidExpression.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidInnerBean.xml b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidInnerBean.xml new file mode 100644 index 0000000000..e2da4dcde0 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidInnerBean.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidRef.xml b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidRef.xml new file mode 100644 index 0000000000..41fc255695 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests-invalidRef.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests.java b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests.java index 46b4f879d4..4cbcc33a14 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/splitter/SplitterIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2011 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. @@ -16,17 +16,20 @@ package org.springframework.integration.splitter; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.BeanCreationException; 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.annotation.MessageEndpoint; @@ -40,23 +43,24 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Iwein Fuld * @author Alexander Peters + * @author Mark Fisher */ -@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) public class SplitterIntegrationTests { @Autowired - @Qualifier("inAnnotated") MessageChannel inAnnotated; @Autowired - @Qualifier("inMethodInvoking") MessageChannel inMethodInvoking; @Autowired - @Qualifier("inDefault") MessageChannel inDefault; - + + @Autowired + MessageChannel inDelimiters; + @Autowired MethodInvokingSplitter splitter; @@ -67,9 +71,13 @@ public class SplitterIntegrationTests { @Autowired Receiver receiver; + @Before + public void clearWords() { + receiver.receivedWords.clear(); + } + @MessageEndpoint public static class Receiver { - private List receivedWords = new ArrayList(); @ServiceActivator(inputChannel = "out") @@ -113,7 +121,55 @@ public class SplitterIntegrationTests { assertTrue(receiver.receivedWords.containsAll(words)); assertTrue(words.containsAll(receiver.receivedWords)); } - + + @Test + public void delimiterSplitter() throws Exception { + inDelimiters.send(new GenericMessage("one,two, three; four/five")); + assertTrue(receiver.receivedWords.containsAll(Arrays.asList("one", "two", "three", "four", "five"))); + } + + @Test(expected = IllegalArgumentException.class) + public void delimitersNotAllowedWithRef() throws Throwable { + try { + new ClassPathXmlApplicationContext("SplitterIntegrationTests-invalidRef.xml", SplitterIntegrationTests.class); + } + catch (BeanCreationException e) { + Throwable cause = e.getMostSpecificCause(); + assertNotNull(cause); + assertTrue(cause instanceof IllegalArgumentException); + assertTrue(cause.getMessage().contains("'delimiters' property is only available")); + throw cause; + } + } + + @Test(expected = IllegalArgumentException.class) + public void delimitersNotAllowedWithInnerBean() throws Throwable { + try { + new ClassPathXmlApplicationContext("SplitterIntegrationTests-invalidInnerBean.xml", SplitterIntegrationTests.class); + } + catch (BeanCreationException e) { + Throwable cause = e.getMostSpecificCause(); + assertNotNull(cause); + assertTrue(cause instanceof IllegalArgumentException); + assertTrue(cause.getMessage().contains("'delimiters' property is only available")); + throw cause; + } + } + + @Test(expected = IllegalArgumentException.class) + public void delimitersNotAllowedWithExpression() throws Throwable { + try { + new ClassPathXmlApplicationContext("SplitterIntegrationTests-invalidExpression.xml", SplitterIntegrationTests.class); + } + catch (BeanCreationException e) { + Throwable cause = e.getMostSpecificCause(); + assertNotNull(cause); + assertTrue(cause instanceof IllegalArgumentException); + assertTrue(cause.getMessage().contains("'delimiters' property is only available")); + throw cause; + } + } + @Test public void channelResolver_isNotNull() throws Exception { splitter.setOutputChannel(null);