INT-1932 added support for 'delimiters' attribute on the <splitter> element (when not using a 'ref', 'expression', or inner bean)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1088,24 +1088,7 @@ endpoint itself is a Polling Consumer for a channel with a queue.
|
||||
<xsd:any processContents="strict" namespace="##other" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
||||
<xsd:element name="service-activator" type="expressionOrInnerEndpointDefinitionAware" />
|
||||
<xsd:element name="splitter">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:attribute name="apply-sequence" type="xsd:boolean" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="splitter" type="splitter-type" />
|
||||
<xsd:element name="transformer" type="expressionOrInnerEndpointDefinitionAware" />
|
||||
<xsd:element name="header-enricher" type="header-enricher-type" />
|
||||
<xsd:element name="header-filter" type="header-filter-type" />
|
||||
@@ -2356,34 +2339,48 @@ Name of the header whose value will be used to route messages
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:extension base="splitter-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
<xsd:attribute name="requires-reply" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="apply-sequence" type="xsd:boolean" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="splitter-type">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:attribute name="requires-reply" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="apply-sequence" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="delimiters" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="aggregator">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
|
||||
<splitter input-channel="inDefault" output-channel="out" />
|
||||
|
||||
<splitter input-channel="inDelimiters" output-channel="out" delimiters=",;/ " />
|
||||
|
||||
<beans:bean id="splitterBeanXmlConfig"
|
||||
class="org.springframework.integration.splitter.SplitterIntegrationTests$TestSplitter" />
|
||||
|
||||
<beans:bean id="splitterBeanAnnotationConfig"
|
||||
class="org.springframework.integration.splitter.SplitterIntegrationTests$TestSplitter" />
|
||||
|
||||
<beans:bean
|
||||
class="org.springframework.integration.splitter.SplitterIntegrationTests$Receiver" />
|
||||
<beans:bean class="org.springframework.integration.splitter.SplitterIntegrationTests$Receiver" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<channel id="out">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<splitter input-channel="in" output-channel="out" delimiters="," expression="'foo,bar'"/>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<channel id="out">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<splitter input-channel="in" output-channel="out" delimiters=",;/ ">
|
||||
<beans:bean id="bean" class="org.springframework.integration.splitter.SplitterIntegrationTests$Receiver"/>
|
||||
</splitter>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<channel id="out">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<splitter input-channel="in" output-channel="out" delimiters=",;/ " ref="bean"/>
|
||||
|
||||
<beans:bean id="bean" class="org.springframework.integration.splitter.SplitterIntegrationTests$Receiver"/>
|
||||
|
||||
</beans:beans>
|
||||
@@ -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<String> receivedWords = new ArrayList<String>();
|
||||
|
||||
@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<String>("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);
|
||||
|
||||
Reference in New Issue
Block a user