diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java
index 5e13e63032..6948e7ee06 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessor.java
@@ -16,7 +16,12 @@
package org.springframework.integration.handler;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.expression.MapAccessor;
+import org.springframework.expression.AccessException;
+import org.springframework.expression.BeanResolver;
+import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParseException;
@@ -31,7 +36,7 @@ import org.springframework.integration.core.Message;
* @author Mark Fisher
* @since 2.0
*/
-public class ExpressionEvaluatingMessageProcessor extends AbstractMessageProcessor {
+public class ExpressionEvaluatingMessageProcessor extends AbstractMessageProcessor implements BeanFactoryAware {
private final ExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
@@ -40,6 +45,9 @@ public class ExpressionEvaluatingMessageProcessor extends AbstractMessageProcess
private volatile Class> expectedType = null;
+ /**
+ * Create an {@link ExpressionEvaluatingMessageProcessor} for the given expression String.
+ */
public ExpressionEvaluatingMessageProcessor(String expression) {
try {
this.expression = parser.parseExpression(expression);
@@ -51,10 +59,30 @@ public class ExpressionEvaluatingMessageProcessor extends AbstractMessageProcess
}
+ /**
+ * Set the result type expected from evaluation of the expression.
+ */
public void setExpectedType(Class> expectedType) {
this.expectedType = expectedType;
}
+ /**
+ * Specify a BeanFactory in order to enable resolution via @beanName in the expression.
+ */
+ public void setBeanFactory(final BeanFactory beanFactory) {
+ if (beanFactory != null) {
+ this.getEvaluationContext().setBeanResolver(new BeanResolver() {
+ public Object resolve(EvaluationContext context, String beanName) throws AccessException {
+ return beanFactory.getBean(beanName);
+ }
+ });
+ }
+ }
+
+ /**
+ * Processes the Message by evaluating the expression with that Message as the
+ * root object. The expression evaluation result Object will be returned.
+ */
public Object processMessage(Message> message) {
return this.evaluateExpression(this.expression, message, this.expectedType);
}
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessorTests.java
index 26e6d0fd1c..d24d4b3fbf 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessorTests.java
+++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/ExpressionEvaluatingMessageProcessorTests.java
@@ -22,22 +22,28 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.internal.matchers.TypeSafeMatcher;
import org.junit.rules.ExpectedException;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.support.StaticApplicationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.StringMessage;
/**
* @author Dave Syer
+ * @author Mark Fisher
* @since 2.0
- *
*/
public class ExpressionEvaluatingMessageProcessorTests {
private static final Log logger = LogFactory.getLog(ExpressionEvaluatingMessageProcessorTests.class);
+
@Rule
public ExpectedException expected = ExpectedException.none();
+
@Test
public void testProcessMessage() {
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload");
@@ -45,12 +51,19 @@ public class ExpressionEvaluatingMessageProcessorTests {
}
@Test
- public void testProcessMessageWithDollar() {
+ public void testProcessMessageWithDollarInBrackets() {
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers['$id']");
StringMessage message = new StringMessage("foo");
assertEquals(message.getHeaders().getId(), processor.processMessage(message));
}
+ @Test
+ public void testProcessMessageWithDollarPropertyAccess() {
+ ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers.$id");
+ StringMessage message = new StringMessage("foo");
+ assertEquals(message.getHeaders().getId(), processor.processMessage(message));
+ }
+
@Test
public void testProcessMessageWithStaticKey() {
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers[headers.ID]");
@@ -58,6 +71,30 @@ public class ExpressionEvaluatingMessageProcessorTests {
assertEquals(message.getHeaders().getId(), processor.processMessage(message));
}
+ @Test
+ public void testProcessMessageWithBeanAsMethodArgument() {
+ StaticApplicationContext context = new StaticApplicationContext();
+ BeanDefinition beanDefinition = new RootBeanDefinition(String.class);
+ beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("bar");
+ context.registerBeanDefinition("testString", beanDefinition);
+ ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.concat(@testString)");
+ processor.setBeanFactory(context);
+ StringMessage message = new StringMessage("foo");
+ assertEquals("foobar", processor.processMessage(message));
+ }
+
+ @Test
+ public void testProcessMessageWithMethodCallOnBean() {
+ StaticApplicationContext context = new StaticApplicationContext();
+ BeanDefinition beanDefinition = new RootBeanDefinition(String.class);
+ beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("bar");
+ context.registerBeanDefinition("testString", beanDefinition);
+ ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("@testString.concat(payload)");
+ processor.setBeanFactory(context);
+ StringMessage message = new StringMessage("foo");
+ assertEquals("barfoo", processor.processMessage(message));
+ }
+
@Test
public void testProcessMessageBadExpression() {
expected.expect(new TypeSafeMatcher(Exception.class) {
@@ -90,8 +127,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
description.appendText("cause to be UnsupportedOperationException but was ").appendValue(cause);
}
});
- ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.error()");
- assertEquals("foo", processor.processMessage(new GenericMessage(this)));
+ ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.throwRuntimeException()");
+ assertEquals("foo", processor.processMessage(new GenericMessage(new TestPayload())));
}
@Test
@@ -108,17 +145,23 @@ public class ExpressionEvaluatingMessageProcessorTests {
description.appendText("cause to be CheckedException but was ").appendValue(cause);
}
});
- ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.check()");
- assertEquals("foo", processor.processMessage(new GenericMessage(this)));
+ ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.throwCheckedException()");
+ assertEquals("foo", processor.processMessage(new GenericMessage(new TestPayload())));
}
- public String error() {
- throw new UnsupportedOperationException("Expected test exception");
+
+ @SuppressWarnings("unused")
+ private static class TestPayload {
+
+ public String throwRuntimeException() {
+ throw new UnsupportedOperationException("Expected test exception");
+ }
+
+ public String throwCheckedException() throws Exception {
+ throw new CheckedException("Expected test exception");
+ }
}
- public String check() throws Exception {
- throw new CheckedException("Expected test exception");
- }
@SuppressWarnings("serial")
private static final class CheckedException extends Exception {