INT-1760, INT-1759 Http outbound gateway response type

Change the default expected response type to ResponseEntity

Add support for expected-response-type-expression attribute
to accept SpEL to determine expected response type.

INT-1760, INT-1759 add documentation.

INT-1760, INT-1759 polished javadocs and schema doc

INT-1760, INT-1759 more polishing

INT-1760, INT-1759 polished documentation based on PR

INT-1760 Polishing

Fix Chain test.
This commit is contained in:
Oleg Zhurakousky
2012-06-06 12:33:34 -04:00
committed by Gary Russell
parent e6520821d1
commit 6bbe8057ab
12 changed files with 320 additions and 27 deletions

View File

@@ -114,4 +114,30 @@ abstract class HttpAdapterParsingUtils {
}
}
static void setExpectedResponseOrExpression(Element element, ParserContext parserContext, BeanDefinitionBuilder builder){
String expectedResponseType = element.getAttribute("expected-response-type");
String expectedResponseTypeExpression = element.getAttribute("expected-response-type-expression");
boolean hasExpectedResponseType = StringUtils.hasText(expectedResponseType);
boolean hasExpectedResponseTypeExpression = StringUtils.hasText(expectedResponseTypeExpression);
if (hasExpectedResponseType && hasExpectedResponseTypeExpression){
parserContext.getReaderContext().error("The 'expected-response-type' and 'expected-response-type-expression' are mutually exclusive. " +
"You can only have one or the other", element);
}
RootBeanDefinition expressionDef = null;
if (hasExpectedResponseType) {
expressionDef = new RootBeanDefinition(LiteralExpression.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expectedResponseType);
}
else if (hasExpectedResponseTypeExpression){
expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expectedResponseTypeExpression);
}
if (expressionDef != null){
builder.addPropertyValue("expectedResponseTypeExpression", expressionDef);
}
}
}

View File

@@ -73,7 +73,7 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "charset");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expected-response-type");
HttpAdapterParsingUtils.setExpectedResponseOrExpression(element, parserContext, builder);
HttpAdapterParsingUtils.configureUriVariableExpressions(builder, element);
return builder.getBeanDefinition();
}

View File

@@ -79,7 +79,9 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "charset");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-request-payload", "extractPayload");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expected-response-type");
HttpAdapterParsingUtils.setExpectedResponseOrExpression(element, parserContext, builder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
HttpAdapterParsingUtils.configureUriVariableExpressions(builder, element);

View File

@@ -31,6 +31,8 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.MapAccessor;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -89,7 +91,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
private volatile boolean expectReply = true;
private volatile Class<?> expectedResponseType;
private volatile Expression expectedResponseTypeExpression;
private volatile boolean extractPayload = true;
@@ -198,13 +200,26 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
/**
* Specify the expected response type for the REST request.
* If this is null (the default), only the status code will be returned
* as the reply Message payload. To take advantage of the HttpMessageConverters
* Specify the expected response type for the REST request
* otherwise the default response type is {@link ResponseEntity} and will
* be returned as a payload of the reply Message.
* To take advantage of the HttpMessageConverters
* registered on this adapter, provide a different type).
* Also see {@link #setExpectedResponseTypeExpression(Expression)}
*/
public void setExpectedResponseType(Class<?> expectedResponseType) {
this.expectedResponseType = expectedResponseType;
Assert.notNull(expectedResponseType, "'expectedResponseType' must not be null");
this.expectedResponseTypeExpression = new LiteralExpression(expectedResponseType.getName());
}
/**
* Specify the {@link Expression} to determine the type for the expected response
* The returned value of the expression could be an instance of {@link Class} or
* {@link String} representing a fully qualified class name
* Also see {@link #setExpectedResponseTypeExpression(Expression)}
*/
public void setExpectedResponseTypeExpression(Expression expectedResponseTypeExpression) {
this.expectedResponseTypeExpression = expectedResponseTypeExpression;
}
/**
@@ -269,8 +284,19 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
ConversionService conversionService = this.getConversionService();
if (conversionService == null){
conversionService = new GenericConversionService();
}
Assert.isInstanceOf(GenericConversionService.class, conversionService);
GenericConversionService gConversionService = (GenericConversionService) conversionService;
gConversionService.addConverter(new Converter<Class<?>, String>() {
public String convert(Class<?> source) {
return source.getName();
}
});
if (conversionService != null) {
this.evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
this.evaluationContext.setTypeConverter(new StandardTypeConverter(gConversionService));
}
}
@@ -294,8 +320,10 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
}
Class<?> expectedResponseType = this.determineExpectedResponseType(requestMessage);
HttpEntity<?> httpRequest = this.generateHttpRequest(requestMessage, httpMethod);
ResponseEntity<?> httpResponse = this.restTemplate.exchange(uri, httpMethod, httpRequest, this.expectedResponseType, uriVariables);
ResponseEntity<?> httpResponse = this.restTemplate.exchange(uri, httpMethod, httpRequest, expectedResponseType, uriVariables);
if (this.expectReply) {
HttpHeaders httpHeaders = httpResponse.getHeaders();
Map<String, Object> headers = this.headerMapper.toHeaders(httpHeaders);
@@ -310,7 +338,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
return replyBuilder.copyHeaders(headers).build();
}
else {
return MessageBuilder.withPayload(httpResponse.getStatusCode()).
return MessageBuilder.withPayload(httpResponse).
copyHeaders(headers).setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE, httpResponse.getStatusCode()).
build();
}
@@ -490,4 +518,16 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
"The 'httpMethodExpression' returned an invalid HTTP Method value: " + strHttpMethod);
return HttpMethod.valueOf(strHttpMethod);
}
private Class<?> determineExpectedResponseType(Message<?> requestMessage) throws Exception{
Class<?> expectedResponseType = null;
String expectedResponseTypeName = null;
if (this.expectedResponseTypeExpression != null){
expectedResponseTypeName = this.expectedResponseTypeExpression.getValue(this.evaluationContext, requestMessage, String.class);
}
if (StringUtils.hasText(expectedResponseTypeName)){
expectedResponseType = Class.forName(expectedResponseTypeName);
}
return expectedResponseType;
}
}

View File

@@ -411,7 +411,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
<xsd:attribute name="expected-response-type" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The expected type to which the response body should be converted.
The expected type to which the response body should be converted.
Default is 'org.springframework.http.ResponseEntity'.
This attribute cannot be provided if expected-response-type-expression has a value
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="direct">
@@ -420,6 +422,16 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expected-response-type-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
SpEL expression to determine the type for the expected response to which the response body should be converted
The returned value of the expression could be an instance of java.lang.Class or
java.lang.String representing a fully qualified class name.
This attribute cannot be provided if expected-response-type has a value
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="message-converters" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
@@ -595,7 +607,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
<xsd:attribute name="expected-response-type" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The expected type to which the response body should be converted.
The expected type to which the response body should be converted.
Default is 'org.springframework.http.ResponseEntity'.
This attribute cannot be provided if expected-response-type-expression has a value
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="direct">
@@ -604,6 +618,16 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expected-response-type-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
SpEL expression to determine the type for the expected response to which the response body should be converted
The returned value of the expression could be an instance of java.lang.Class or
java.lang.String representing a fully qualified class name.
This attribute cannot be provided if expected-response-type has a value
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="charset" type="xsd:string" />
<xsd:attribute name="request-factory" type="xsd:string">
<xsd:annotation>