INT-28 Added support for headers based on the evaluation of EL expressions provided on the @Publisher annotation.
This commit is contained in:
@@ -35,9 +35,16 @@ interface ExpressionSource {
|
||||
|
||||
|
||||
/**
|
||||
* Returns the expression string to be evaluated.
|
||||
* Returns the expression string to be evaluated for creating the Message
|
||||
* payload.
|
||||
*/
|
||||
String getExpressionString(Method method);
|
||||
String getPayloadExpression(Method method);
|
||||
|
||||
/**
|
||||
* Returns the array of expression strings to be evaluated for any headers
|
||||
* that should be set on the published Message.
|
||||
*/
|
||||
String[] getHeaderExpressions(Method method);
|
||||
|
||||
/**
|
||||
* Returns the variable names to be associated with the intercepted method
|
||||
|
||||
@@ -26,8 +26,10 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
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;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParserConfiguration;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -35,9 +37,9 @@ import org.springframework.integration.channel.ChannelResolver;
|
||||
import org.springframework.integration.channel.MessageChannelTemplate;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.gateway.SimpleMessageMapper;
|
||||
import org.springframework.integration.message.InboundMessageMapper;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link MethodInterceptor} that publishes Messages to a channel. The
|
||||
@@ -58,8 +60,6 @@ public class MessagePublishingInterceptor implements MethodInterceptor {
|
||||
SpelExpressionParserConfiguration.CreateObjectIfAttemptToReferenceNull |
|
||||
SpelExpressionParserConfiguration.GrowListsOnIndexBeyondSize);
|
||||
|
||||
private final InboundMessageMapper<Object> messageMapper = new SimpleMessageMapper();
|
||||
|
||||
private volatile ChannelResolver channelResolver;
|
||||
|
||||
|
||||
@@ -109,12 +109,19 @@ public class MessagePublishingInterceptor implements MethodInterceptor {
|
||||
}
|
||||
|
||||
private void publishMessage(Method method, EvaluationContext context) throws Exception {
|
||||
String expressionString = this.expressionSource.getExpressionString(method);
|
||||
if (expressionString != null) {
|
||||
Expression expression = this.parser.parseExpression(expressionString);
|
||||
String payloadExpressionString = this.expressionSource.getPayloadExpression(method);
|
||||
if (payloadExpressionString != null) {
|
||||
Expression expression = this.parser.parseExpression(payloadExpressionString);
|
||||
Object result = expression.getValue(context);
|
||||
if (result != null) {
|
||||
Message<?> message = this.messageMapper.toMessage(result);
|
||||
MessageBuilder<?> builder = (result instanceof Message<?>)
|
||||
? MessageBuilder.fromMessage((Message<?>) result)
|
||||
: MessageBuilder.withPayload(result);
|
||||
Map<String, Object> headers = this.evaluateHeaders(method, context);
|
||||
if (headers != null) {
|
||||
builder.copyHeaders(headers);
|
||||
}
|
||||
Message<?> message = builder.build();
|
||||
String channelName = this.expressionSource.getChannelName(method);
|
||||
MessageChannel channel = null;
|
||||
if (channelName != null) {
|
||||
@@ -131,4 +138,24 @@ public class MessagePublishingInterceptor implements MethodInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> evaluateHeaders(Method method, EvaluationContext context)
|
||||
throws ParseException, EvaluationException {
|
||||
|
||||
String[] headerExpressionStrings = this.expressionSource.getHeaderExpressions(method);
|
||||
if (headerExpressionStrings != null) {
|
||||
Map<String, Object> headers = new HashMap<String, Object>();
|
||||
context.setRootObject(headers);
|
||||
for (String headerExpression : headerExpressionStrings) {
|
||||
if (StringUtils.hasText(headerExpression)) {
|
||||
Expression expression = this.parser.parseExpression(headerExpression);
|
||||
expression.getValue(context);
|
||||
}
|
||||
}
|
||||
if (headers.size() > 0) {
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,10 +58,14 @@ public class MethodAnnotationExpressionSource implements ExpressionSource {
|
||||
this.channelAttributeName = channelAttributeName;
|
||||
}
|
||||
|
||||
public String getExpressionString(Method method) {
|
||||
public String getPayloadExpression(Method method) {
|
||||
return this.getAnnotationValue(method, null, String.class);
|
||||
}
|
||||
|
||||
public String[] getHeaderExpressions(Method method) {
|
||||
return this.getAnnotationValue(method, "headers", String[].class);
|
||||
}
|
||||
|
||||
public String[] getArgumentNames(Method method) {
|
||||
ExpressionBinding annotation = AnnotationUtils.findAnnotation(method, ExpressionBinding.class);
|
||||
if (annotation != null) {
|
||||
|
||||
@@ -34,10 +34,17 @@ import java.lang.annotation.Target;
|
||||
public @interface Publisher {
|
||||
|
||||
/**
|
||||
* String representation of a Spel Expression. Required.
|
||||
* String representation of a Spel Expression to evaluate when creating the
|
||||
* Message payload. Required.
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* String representations of Spel Expressions to evaluate for adding any
|
||||
* headers to the Message. Optional.
|
||||
*/
|
||||
String[] headers() default "";
|
||||
|
||||
/**
|
||||
* Name of the Message Channel to which Messages will be published.
|
||||
*/
|
||||
|
||||
@@ -88,22 +88,25 @@ public class MessagePublishingInterceptorTests {
|
||||
return new String[] { "a1", "a2" };
|
||||
}
|
||||
|
||||
public String getChannelName(Method method) {
|
||||
return "c";
|
||||
public String getReturnValueName(Method method) {
|
||||
return "r";
|
||||
}
|
||||
|
||||
public String getExceptionName(Method method) {
|
||||
return "x";
|
||||
}
|
||||
|
||||
public String getExpressionString(Method method) {
|
||||
public String getPayloadExpression(Method method) {
|
||||
return "#r";
|
||||
}
|
||||
|
||||
public String getReturnValueName(Method method) {
|
||||
return "r";
|
||||
public String[] getHeaderExpressions(Method method) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getChannelName(Method method) {
|
||||
return "c";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.aop;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -33,11 +34,15 @@ public class MethodAnnotationExpressionSourceTests {
|
||||
@Test
|
||||
public void defaultBindings() {
|
||||
Method method = getMethod("methodWithExpressionAnnotationOnly", String.class, int.class);
|
||||
String expressionString = source.getExpressionString(method);
|
||||
String expressionString = source.getPayloadExpression(method);
|
||||
assertEquals("testExpression1", expressionString);
|
||||
assertEquals(2, source.getArgumentNames(method).length);
|
||||
assertEquals("arg1", source.getArgumentNames(method)[0]);
|
||||
assertEquals("arg2", source.getArgumentNames(method)[1]);
|
||||
String[] headerStrings = source.getHeaderExpressions(method);
|
||||
assertNotNull(headerStrings);
|
||||
assertEquals(1, headerStrings.length);
|
||||
assertEquals("", headerStrings[0]);
|
||||
assertEquals(ExpressionSource.DEFAULT_ARGUMENT_MAP_NAME, source.getArgumentMapName(method));
|
||||
assertEquals(ExpressionSource.DEFAULT_EXCEPTION_NAME, source.getExceptionName(method));
|
||||
assertEquals(ExpressionSource.DEFAULT_RETURN_VALUE_NAME, source.getReturnValueName(method));
|
||||
@@ -46,7 +51,7 @@ public class MethodAnnotationExpressionSourceTests {
|
||||
@Test
|
||||
public void annotationBindings() {
|
||||
Method method = getMethod("methodWithExpressionBinding", String.class, int.class);
|
||||
String expressionString = source.getExpressionString(method);
|
||||
String expressionString = source.getPayloadExpression(method);
|
||||
assertEquals("testExpression2", expressionString);
|
||||
assertEquals(2, source.getArgumentNames(method).length);
|
||||
assertEquals("s", source.getArgumentNames(method)[0]);
|
||||
@@ -78,7 +83,7 @@ public class MethodAnnotationExpressionSourceTests {
|
||||
public void methodWithExpressionAnnotationOnly(String arg1, int arg2) {
|
||||
}
|
||||
|
||||
@Publisher(value="#return", channel="foo")
|
||||
@Publisher(value="#return", channel="foo", headers="bar=123")
|
||||
public void methodWithChannelAndReturnAsPayload() {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user