Skip to content

Commit

Permalink
Merge pull request spring-projects#480 from olegz/INT-1760
Browse files Browse the repository at this point in the history
  • Loading branch information
garyrussell committed Jun 7, 2012
2 parents e652082 + 6bbe805 commit 5232b83
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,30 @@ else if (hasHttpMethodExpression){
}
}

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ else if (StringUtils.hasText(mappedRequestHeaders)) {
}
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ protected BeanDefinitionBuilder parseHandler(Element element, ParserContext pars
}
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -198,13 +200,26 @@ public void setExpectReply(boolean expectReply) {
}

/**
* 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;
}

/**
Expand Down Expand Up @@ -269,8 +284,19 @@ public void onInit() {
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));
}
}

Expand All @@ -294,8 +320,10 @@ protected Object handleRequestMessage(Message<?> requestMessage) {
}
}

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);
Expand All @@ -310,7 +338,7 @@ protected Object handleRequestMessage(Message<?> requestMessage) {
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();
}
Expand Down Expand Up @@ -490,4 +518,16 @@ private HttpMethod determineHttpMethod(Message<?> requestMessage) {
"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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -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>
Expand Down Expand Up @@ -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">
Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
Expand Down Expand Up @@ -118,7 +118,7 @@ public void fullConfig() {
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(handlerAccessor.getPropertyValue("restTemplate"));
ClientHttpRequestFactory requestFactory = (ClientHttpRequestFactory)
templateAccessor.getPropertyValue("requestFactory");
assertEquals(Boolean.class, handlerAccessor.getPropertyValue("expectedResponseType"));
assertEquals(Boolean.class.getName(), TestUtils.getPropertyValue(handler, "expectedResponseTypeExpression", Expression.class).getValue());
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
Object converterListBean = this.applicationContext.getBean("converterList");
assertEquals(converterListBean, templateAccessor.getPropertyValue("messageConverters"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2012 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.
Expand Down Expand Up @@ -108,7 +108,8 @@ public void fullConfig() throws Exception {
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
Object converterListBean = this.applicationContext.getBean("converterList");
assertEquals(converterListBean, templateAccessor.getPropertyValue("messageConverters"));
assertEquals(String.class, handlerAccessor.getPropertyValue("expectedResponseType"));

assertEquals(String.class.getName(), TestUtils.getPropertyValue(handler, "expectedResponseTypeExpression", Expression.class).getValue());
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
assertEquals("http://localhost/test2", uriExpression.getValue());
assertEquals(HttpMethod.PUT.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-2.2.xsd">


<int-http:outbound-gateway url="http://localhost:51235/testApps/outboundResponse"
request-channel="resTypeSetChannel"
reply-channel="replyChannel"
expected-response-type="java.lang.String"
expected-response-type-expression="payload"/>


<int:channel id="replyChannel">
<int:queue/>
</int:channel>

</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-2.2.xsd">


<int-http:outbound-gateway url="http://localhost:51235/testApps/outboundResponse"
request-channel="requestChannel"
reply-channel="replyChannel"/>

<int-http:outbound-gateway url="http://localhost:51235/testApps/outboundResponse"
request-channel="resTypeSetChannel"
reply-channel="replyChannel"
expected-response-type="java.lang.String"/>

<int-http:outbound-gateway url="http://localhost:51235/testApps/outboundResponse"
request-channel="resTypeExpressionSetChannel"
reply-channel="replyChannel"
expected-response-type-expression="payload"/>

<int:channel id="replyChannel">
<int:queue/>
</int:channel>

</beans>
Loading

0 comments on commit 5232b83

Please sign in to comment.