diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java
index 259acaf91d..0df3c9670e 100644
--- a/org.springframework.integration/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java
+++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/SplitterFactoryBean.java
@@ -19,6 +19,7 @@ package org.springframework.integration.config;
import org.springframework.integration.message.MessageHandler;
import org.springframework.integration.splitter.AbstractMessageSplitter;
import org.springframework.integration.splitter.DefaultMessageSplitter;
+import org.springframework.integration.splitter.ExpressionEvaluatingSplitter;
import org.springframework.integration.splitter.MethodInvokingSplitter;
import org.springframework.util.StringUtils;
@@ -39,6 +40,11 @@ public class SplitterFactoryBean extends AbstractMessageHandlerFactoryBean {
: new MethodInvokingSplitter(targetObject);
}
+ @Override
+ protected MessageHandler createExpressionEvaluatingHandler(String expression) {
+ return new ExpressionEvaluatingSplitter(expression);
+ }
+
@Override
protected MessageHandler createDefaultHandler() {
return new DefaultMessageSplitter();
diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SplitterParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SplitterParser.java
index db8b79837f..1408d791d3 100644
--- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SplitterParser.java
+++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SplitterParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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,18 +33,41 @@ public class SplitterParser extends AbstractConsumerEndpointParser {
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
- BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".config.SplitterFactoryBean");
- if (innerDefinition != null){
- builder.addPropertyValue("targetObject", innerDefinition);
- } else if (element.hasAttribute(REF_ATTRIBUTE)) {
- String ref = element.getAttribute(REF_ATTRIBUTE);
- builder.addPropertyReference("targetObject", ref);
- if (StringUtils.hasText(element.getAttribute(METHOD_ATTRIBUTE))) {
- String method = element.getAttribute(METHOD_ATTRIBUTE);
- builder.addPropertyValue("targetMethodName", method);
+
+ BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
+ String ref = element.getAttribute(REF_ATTRIBUTE);
+ String expression = element.getAttribute(EXPRESSION_ATTRIBUTE);
+ boolean hasRef = StringUtils.hasText(ref);
+ boolean hasExpression = StringUtils.hasText(expression);
+
+ if (innerDefinition != null) {
+ if (hasRef || hasExpression) {
+ parserContext.getReaderContext().error(
+ "Neither 'ref' nor 'expression' are permitted when an inner bean () is configured.", element);
+ return null;
}
+ builder.addPropertyValue("targetObject", innerDefinition);
+ }
+ else if (hasRef) {
+ builder.addPropertyReference("targetObject", ref);
+ }
+ else if (hasExpression) {
+ builder.addPropertyValue("expression", expression);
+ }
+ else {
+ // will create a DefaultSplitter
+ return builder;
+ }
+
+ String method = element.getAttribute(METHOD_ATTRIBUTE);
+ if (StringUtils.hasText(method)) {
+ if (hasExpression) {
+ parserContext.getReaderContext().error(
+ "A 'method' attribute is not permitted when configuring an 'expression'.", element);
+ }
+ builder.addPropertyValue("targetMethodName", method);
}
return builder;
}
diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java
index 95f60d81cd..a656c18fbe 100644
--- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java
+++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java
@@ -36,16 +36,20 @@ import org.springframework.integration.message.MessageHandlingException;
*/
public class ExpressionEvaluatingMessageProcessor implements MessageProcessor {
- private final ExpressionParser parser = new SpelExpressionParser(
+ /*private final ExpressionParser parser = new SpelExpressionParser(
SpelExpressionParserConfiguration.CreateObjectIfAttemptToReferenceNull |
SpelExpressionParserConfiguration.GrowListsOnIndexBeyondSize);
+ */
private final Expression expression;
public ExpressionEvaluatingMessageProcessor(String expression) {
try {
- this.expression = this.parser.parseExpression(expression);
+ ExpressionParser parser = new SpelExpressionParser(
+ SpelExpressionParserConfiguration.CreateObjectIfAttemptToReferenceNull |
+ SpelExpressionParserConfiguration.GrowListsOnIndexBeyondSize);
+ this.expression = parser.parseExpression(expression);
}
catch (ParseException e) {
throw new IllegalArgumentException("Failed to parse expression.", e);
diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/splitter/AbstractMessageProcessingSplitter.java b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/AbstractMessageProcessingSplitter.java
new file mode 100644
index 0000000000..a7681a94db
--- /dev/null
+++ b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/AbstractMessageProcessingSplitter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2009 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.splitter;
+
+import org.springframework.integration.core.Message;
+import org.springframework.integration.handler.MessageProcessor;
+import org.springframework.util.Assert;
+
+/**
+ * Base class for Message Splitter implementations that delegate to a
+ * {@link MessageProcessor} instance.
+ *
+ * @author Mark Fisher
+ * @since 2.0
+ */
+abstract class AbstractMessageProcessingSplitter extends AbstractMessageSplitter {
+
+ private final MessageProcessor messageProcessor;
+
+
+ protected AbstractMessageProcessingSplitter(MessageProcessor messageProcessor) {
+ Assert.notNull(messageProcessor, "messageProcessor must not be null");
+ this.messageProcessor = messageProcessor;
+ }
+
+ @Override
+ protected final Object splitMessage(Message> message) {
+ return this.messageProcessor.processMessage(message);
+ }
+
+}
diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/splitter/ExpressionEvaluatingSplitter.java b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/ExpressionEvaluatingSplitter.java
new file mode 100644
index 0000000000..55955fb424
--- /dev/null
+++ b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/ExpressionEvaluatingSplitter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2009 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.splitter;
+
+import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
+
+/**
+ * A Message Splitter implementation that evaluates the specified SpEL
+ * expression. The result of evaluation will typically be a Collection or
+ * Array. If the result is not a Collection or Array, then the single Object
+ * will be returned as the payload of a single reply Message.
+ *
+ * @author Mark Fisher
+ * @since 2.0
+ */
+public class ExpressionEvaluatingSplitter extends AbstractMessageProcessingSplitter {
+
+ public ExpressionEvaluatingSplitter(String expression) {
+ super(new ExpressionEvaluatingMessageProcessor(expression));
+ }
+
+}
diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java
index 5816490e96..5b9dcc4d44 100644
--- a/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java
+++ b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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,7 +19,6 @@ package org.springframework.integration.splitter;
import java.lang.reflect.Method;
import org.springframework.integration.annotation.Splitter;
-import org.springframework.integration.core.Message;
import org.springframework.integration.handler.MessageMappingMethodInvoker;
/**
@@ -31,27 +30,18 @@ import org.springframework.integration.handler.MessageMappingMethodInvoker;
*
* @author Mark Fisher
*/
-public class MethodInvokingSplitter extends AbstractMessageSplitter {
-
- private final MessageMappingMethodInvoker invoker;
-
+public class MethodInvokingSplitter extends AbstractMessageProcessingSplitter {
public MethodInvokingSplitter(Object object, Method method) {
- this.invoker = new MessageMappingMethodInvoker(object, method);
+ super(new MessageMappingMethodInvoker(object, method));
}
public MethodInvokingSplitter(Object object, String methodName) {
- this.invoker = new MessageMappingMethodInvoker(object, methodName);
+ super(new MessageMappingMethodInvoker(object, methodName));
}
public MethodInvokingSplitter(Object object) {
- this.invoker = new MessageMappingMethodInvoker(object, Splitter.class);
- }
-
-
- @Override
- protected Object splitMessage(Message> message) {
- return this.invoker.processMessage(message);
+ super(new MessageMappingMethodInvoker(object, Splitter.class));
}
}
diff --git a/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd b/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd
index 822e2f084f..771490f532 100644
--- a/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd
+++ b/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd
@@ -959,19 +959,12 @@
-
+
Defines a Transformer.
-
-
-
-
-
-
-
@@ -1205,7 +1198,7 @@
-
+
Defines a Splitter.
@@ -1440,6 +1433,14 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/splitter/SpelSplitterIntegrationTests-context.xml b/org.springframework.integration/src/test/java/org/springframework/integration/splitter/SpelSplitterIntegrationTests-context.xml
new file mode 100644
index 0000000000..f3b830e939
--- /dev/null
+++ b/org.springframework.integration/src/test/java/org/springframework/integration/splitter/SpelSplitterIntegrationTests-context.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/splitter/SpelSplitterIntegrationTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/splitter/SpelSplitterIntegrationTests.java
new file mode 100644
index 0000000000..655df8fbe5
--- /dev/null
+++ b/org.springframework.integration/src/test/java/org/springframework/integration/splitter/SpelSplitterIntegrationTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2009 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.splitter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.integration.channel.PollableChannel;
+import org.springframework.integration.core.Message;
+import org.springframework.integration.core.MessageChannel;
+import org.springframework.integration.message.MessageBuilder;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Mark Fisher
+ */
+@ContextConfiguration
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SpelSplitterIntegrationTests {
+
+ @Autowired @Qualifier("input")
+ private MessageChannel input;
+
+ @Autowired @Qualifier("output")
+ private PollableChannel output;
+
+
+ @Test
+ public void split() {
+ Message> message = MessageBuilder.withPayload(new TestBean()).build();
+ this.input.send(message);
+ assertEquals(new Integer(1), output.receive(0).getPayload());
+ assertEquals(new Integer(2), output.receive(0).getPayload());
+ assertEquals(new Integer(3), output.receive(0).getPayload());
+ assertEquals(new Integer(4), output.receive(0).getPayload());
+ assertNull(output.receive(0));
+ }
+
+
+ static class TestBean {
+
+ private final List numbers = new ArrayList();
+
+ public TestBean() {
+ for (int i = 1; i <= 10; i++) {
+ this.numbers.add(i);
+ }
+ }
+
+ public List getNumbers() {
+ return this.numbers;
+ }
+ }
+
+}