INT-931 header-enricher now supports method invocation

This commit is contained in:
Mark Fisher
2009-12-23 21:49:54 +00:00
parent 99a577372e
commit f0ba127305
5 changed files with 84 additions and 19 deletions

View File

@@ -28,7 +28,6 @@ import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.transformer.HeaderEnricher.ExpressionHolder;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -115,23 +114,50 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
String value = headerElement.getAttribute("value");
String ref = headerElement.getAttribute("ref");
String expression = headerElement.getAttribute("expression");
String method = headerElement.getAttribute("method");
boolean isValue = StringUtils.hasText(value);
boolean isRef = StringUtils.hasText(ref);
boolean isExpression = StringUtils.hasText(expression);
boolean hasMethod = StringUtils.hasText(method);
if (!(isValue ^ (isRef ^ isExpression))) {
parserContext.getReaderContext().error(
"Exactly one of the 'ref', 'value', or 'expression' attributes is required.", element);
}
if (isValue) {
if (hasMethod) {
parserContext.getReaderContext().error(
"The 'method' attribute cannot be used with the 'value' attribute.", element);
}
Object headerValue = (headerType != null) ?
new TypedStringValue(value, headerType) : value;
headers.put(headerName, headerValue);
}
else if (isExpression) {
headers.put(headerName, new ExpressionHolder(expression, headerType));
if (hasMethod) {
parserContext.getReaderContext().error(
"The 'method' attribute cannot be used with the 'expression' attribute.", element);
}
BeanDefinitionBuilder expressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".transformer.HeaderEnricher$ExpressionHolder");
expressionBuilder.addConstructorArgValue(expression);
expressionBuilder.addConstructorArgValue(headerType);
headers.put(headerName, expressionBuilder.getBeanDefinition());
}
else {
headers.put(headerName, new RuntimeBeanReference(ref));
if (StringUtils.hasText(headerElement.getAttribute("type"))) {
parserContext.getReaderContext().error(
"The 'type' attribute cannot be used with the 'ref' attribute.", element);
}
if (hasMethod) {
BeanDefinitionBuilder methodExpressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".transformer.HeaderEnricher$MethodExpressionHolder");
methodExpressionBuilder.addConstructorArgReference(ref);
methodExpressionBuilder.addConstructorArgValue(method);
headers.put(headerName, methodExpressionBuilder.getBeanDefinition());
}
else {
headers.put(headerName, new RuntimeBeanReference(ref));
}
}
}
}

View File

@@ -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.
@@ -20,6 +20,7 @@ import java.util.HashMap;
import java.util.Map;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
@@ -28,6 +29,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessagingException;
import org.springframework.integration.handler.MethodInvokingMessageProcessor;
import org.springframework.integration.message.MessageBuilder;
import org.springframework.util.Assert;
@@ -69,6 +71,9 @@ public class HeaderEnricher implements Transformer {
if (value instanceof ExpressionHolder) {
value = ((ExpressionHolder) value).evaluate(message);
}
else if (value instanceof MethodExpressionHolder) {
value = ((MethodExpressionHolder) value).evaluate(message);
}
headerMap.put(key, value);
}
}
@@ -80,16 +85,15 @@ public class HeaderEnricher implements Transformer {
}
public static class ExpressionHolder {
static class ExpressionHolder {
private static final ExpressionParser parser = new SpelExpressionParser();
private final String expressionString;
private final Class<?> expectedType;
private volatile Expression parsedExpression;
private final Expression expression;
private final EvaluationContext evaluationContext;
/**
@@ -97,22 +101,32 @@ public class HeaderEnricher implements Transformer {
* of the expression evaluation result. The expectedType may be null if unknown.
*/
public ExpressionHolder(String expressionString, Class<?> expectedType) {
this.expressionString = expressionString;
this.expectedType = expectedType;
this.expression = parser.parseExpression(expressionString);
StandardEvaluationContext context = new StandardEvaluationContext();
context.addPropertyAccessor(new MapAccessor());
this.evaluationContext = context;
}
private Object evaluate(Message<?> message) throws ParseException, EvaluationException {
if (this.parsedExpression == null) {
synchronized (this) {
this.parsedExpression = parser.parseExpression(this.expressionString);
}
}
StandardEvaluationContext context = new StandardEvaluationContext(message);
context.addPropertyAccessor(new MapAccessor());
return (this.expectedType != null)
? this.parsedExpression.getValue(context, this.expectedType)
: this.parsedExpression.getValue(context);
? this.expression.getValue(this.evaluationContext, message, this.expectedType)
: this.expression.getValue(this.evaluationContext, message);
}
}
static class MethodExpressionHolder {
private final MethodInvokingMessageProcessor processor;
public MethodExpressionHolder(Object targetObject, String method) {
this.processor = new MethodInvokingMessageProcessor(targetObject, method);
}
private Object evaluate(Message<?> message) {
return this.processor.processMessage(message);
}
}

View File

@@ -989,6 +989,13 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="method" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Name of a method to be invoked on the referenced target object.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:element name="thread-pool-task-executor">

View File

@@ -82,4 +82,12 @@
<header name="number" expression="12345" type="java.lang.Long"/>
</header-enricher>
<header-enricher input-channel="refWithMethod">
<header name="testHeader" ref="testBean" method="getName"/>
</header-enricher>
<beans:bean id="testBean" class="org.springframework.integration.config.xml.HeaderEnricherTests$TestBean">
<beans:constructor-arg value="testBeanForMethodInvoker"/>
</beans:bean>
</beans:beans>

View File

@@ -171,6 +171,16 @@ public class HeaderEnricherTests {
assertEquals(new Long(12345), result.getHeaders().get("number"));
}
@Test
public void refWithMethod() {
SimpleMessagingGateway gateway = new SimpleMessagingGateway();
gateway.setRequestChannel(context.getBean("refWithMethod", MessageChannel.class));
Message<?> result = gateway.sendAndReceiveMessage("test");
assertNotNull(result);
assertEquals(String.class, result.getHeaders().get("testHeader").getClass());
assertEquals("testBeanForMethodInvoker", result.getHeaders().get("testHeader"));
}
public static class TestBean {