INT-1181 added support for bean resolution within the ExpressionEvaluatingMessageProcessor

This commit is contained in:
Mark Fisher
2010-06-16 18:14:16 +00:00
parent 7ba407defe
commit 162214a9b1
2 changed files with 83 additions and 12 deletions

View File

@@ -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 <code>@beanName</code> 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);
}

View File

@@ -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>(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<ExpressionEvaluatingMessageProcessorTests>(this)));
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.throwRuntimeException()");
assertEquals("foo", processor.processMessage(new GenericMessage<TestPayload>(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<ExpressionEvaluatingMessageProcessorTests>(this)));
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.throwCheckedException()");
assertEquals("foo", processor.processMessage(new GenericMessage<TestPayload>(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 {