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();

View File

@@ -213,6 +213,20 @@ public class GatewayProxyFactoryBeanTests {
assertEquals("foobar", result);
}
@Test
public void testNoArgMethodWithPayloadAnnotation() throws Exception {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
TestService service = (TestService) proxyFactory.getObject();
String result = service.requestReplyWithPayloadAnnotation();
assertEquals("requestReplyWithPayloadAnnotation0bar", result);
}
@Test
public void testMessageAsReturnValue() throws Exception {
final QueueChannel requestChannel = new QueueChannel();

View File

@@ -10,6 +10,7 @@
<int:gateway id="gateway" service-interface="org.springframework.integration.gateway.GatewayWithPayloadExpressionTests$SampleGateway">
<int:method name="send1" request-channel="input" payload-expression="#args[0] + 'bar'"/>
<int:method name="send2" request-channel="input" payload-expression="@testBean.sum(#args[0])"/>
<int:method name="send3" request-channel="input" payload-expression="#method"/>
</int:gateway>
<int:gateway id="annotatedGateway"

View File

@@ -67,12 +67,21 @@ public class GatewayWithPayloadExpressionTests {
assertEquals("foobar", result.getPayload());
}
@Test
public void noArgMethodWithPayloadExpression() throws Exception {
gateway.send3();
Message<?> result = input.receive(0);
assertEquals("send3", result.getPayload());
}
public static interface SampleGateway {
void send1(String value);
void send2(String value);
void send3();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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.
@@ -17,6 +17,7 @@
package org.springframework.integration.gateway;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.Payload;
/**
* @author Mark Fisher
@@ -38,4 +39,7 @@ public interface TestService {
Message<?> requestReplyWithMessageReturnValue(String input);
@Payload("#method + #args.length")
String requestReplyWithPayloadAnnotation();
}