No-arg gateway method can be a 'send' operation

- no-arg method will now be a send (instead of receive) if @Payload is present

  - added 'method' to the evaluation context variables with the String value of the invoked method's name

  - added test for new gateway no-arg method send option

  - enable 'payload-expression' in XML for no-arg methods

  - use per-method-invocation evaluation context for header expressions (provides 'args' and 'method' as context variables)
This commit is contained in:
Mark Fisher
2011-09-09 16:16:21 +02:00
parent 08e7287338
commit 74628ccc5f
6 changed files with 55 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -30,6 +30,7 @@ import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -82,7 +83,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
private final Map<String, Expression> parameterPayloadExpressions = new HashMap<String, Expression>();
private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
private final StandardEvaluationContext staticEvaluationContext = new StandardEvaluationContext();
private volatile BeanResolver beanResolver;
@@ -107,7 +108,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
public void setBeanFactory(final BeanFactory beanFactory) {
if (beanFactory != null) {
this.beanResolver = new BeanFactoryResolver(beanFactory);
this.evaluationContext.setBeanResolver(beanResolver);
this.staticEvaluationContext.setBeanResolver(beanResolver);
}
}
@@ -125,13 +126,9 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
Object messageOrPayload = null;
boolean foundPayloadAnnotation = false;
Map<String, Object> headers = new HashMap<String, Object>();
EvaluationContext methodInvocationEvaluationContext = createMethodInvocationEvaluationContext(arguments);
if (this.payloadExpression != null) {
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("args", arguments);
if (this.beanResolver != null) {
context.setBeanResolver(this.beanResolver);
}
messageOrPayload = this.payloadExpression.getValue(context);
messageOrPayload = this.payloadExpression.getValue(methodInvocationEvaluationContext);
}
for (int i = 0; i < this.parameterList.size(); i++) {
Object argumentValue = arguments[i];
@@ -195,7 +192,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
if (!CollectionUtils.isEmpty(this.headerExpressions)) {
Map<String, Object> evaluatedHeaders = new HashMap<String, Object>();
for (Map.Entry<String, Expression> entry : this.headerExpressions.entrySet()) {
Object value = entry.getValue().getValue(this.evaluationContext);
Object value = entry.getValue().getValue(methodInvocationEvaluationContext);
if (value != null) {
evaluatedHeaders.put(entry.getKey(), value);
}
@@ -205,13 +202,23 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
return builder.build();
}
private StandardEvaluationContext createMethodInvocationEvaluationContext(Object[] arguments) {
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("args", arguments);
context.setVariable("method", this.method.getName());
if (this.beanResolver != null) {
context.setBeanResolver(this.beanResolver);
}
return context;
}
private Object evaluatePayloadExpression(String expressionString, Object argumentValue) {
Expression expression = this.parameterPayloadExpressions.get(expressionString);
if (expression == null) {
expression = PARSER.parseExpression(expressionString);
this.parameterPayloadExpressions.put(expressionString, expression);
}
return expression.getValue(this.evaluationContext, argumentValue);
return expression.getValue(this.staticEvaluationContext, argumentValue);
}
private Annotation findMappingAnnotation(Annotation[] annotations) {

View File

@@ -28,7 +28,6 @@ import java.util.concurrent.Future;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.SimpleTypeConverter;
@@ -45,6 +44,7 @@ import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessagingException;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.Payload;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.history.TrackableComponent;
@@ -285,7 +285,13 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab
boolean shouldReply = returnType != void.class;
int paramCount = method.getParameterTypes().length;
Object response = null;
if (paramCount == 0) {
boolean hasPayloadExpression = method.isAnnotationPresent(Payload.class);
if (!hasPayloadExpression && this.methodMetadataMap != null) {
// check for the method metadata next
GatewayMethodMetadata metadata = this.methodMetadataMap.get(method.getName());
hasPayloadExpression = (metadata != null) && StringUtils.hasText(metadata.getPayloadExpression());
}
if (paramCount == 0 && !hasPayloadExpression) {
if (shouldReply) {
if (shouldReturnMessage) {
return gateway.receive();