INT-2397 http-method-expression

Add support for http-method-expression attribute to the HTTP Outbound Gateway/Adapter

INT-2397 polishing

INT-2397 polishing based on PR comments

INT-2397 more polishing based on PR comments

INT-2397 polishing

INT-2397 plishing PR comments

INT-2397 polishing
This commit is contained in:
Oleg Zhurakousky
2012-05-31 20:53:23 -04:00
committed by Gary Russell
parent a011f9dda7
commit b105872bb7
12 changed files with 307 additions and 47 deletions

View File

@@ -18,6 +18,8 @@ package org.springframework.integration.http.config;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -27,7 +29,6 @@ import org.springframework.integration.config.ExpressionFactoryBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* @author Oleg Zhurakousky
@@ -87,5 +88,30 @@ abstract class HttpAdapterParsingUtils {
}
static void setHttpMethodOrExpression(Element element, ParserContext parserContext, BeanDefinitionBuilder builder){
String httpMethod = element.getAttribute("http-method");
String httpMethodExpression = element.getAttribute("http-method-expression");
boolean hasHttpMethod = StringUtils.hasText(httpMethod);
boolean hasHttpMethodExpression = StringUtils.hasText(httpMethodExpression);
if (hasHttpMethod && hasHttpMethodExpression){
parserContext.getReaderContext().error("The 'http-method' and 'http-method-expression' are mutually exclusive. " +
"You can only have one or the other", element);
}
RootBeanDefinition expressionDef = null;
if (hasHttpMethod) {
expressionDef = new RootBeanDefinition(LiteralExpression.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(httpMethod);
}
else if (hasHttpMethodExpression){
expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(httpMethodExpression);
}
if (expressionDef != null){
builder.addPropertyValue("httpMethodExpression", expressionDef);
}
}
}

View File

@@ -16,13 +16,15 @@
package org.springframework.integration.http.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for the 'outbound-channel-adapter' element of the http namespace.
@@ -36,11 +38,11 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HttpRequestExecutingMessageHandler.class);
builder.addPropertyValue("expectReply", false);
HttpAdapterParsingUtils.configureUrlConstructorArg(element, parserContext, builder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "http-method");
HttpAdapterParsingUtils.setHttpMethodOrExpression(element, parserContext, builder);
String restTemplate = element.getAttribute("rest-template");
if (StringUtils.hasText(restTemplate)) {

View File

@@ -16,12 +16,14 @@
package org.springframework.integration.http.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for the 'outbound-gateway' element of the http namespace.
@@ -39,10 +41,11 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HttpRequestExecutingMessageHandler.class);
HttpAdapterParsingUtils.configureUrlConstructorArg(element, parserContext, builder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "http-method");
HttpAdapterParsingUtils.setHttpMethodOrExpression(element, parserContext, builder);
String restTemplate = element.getAttribute("rest-template");
if (StringUtils.hasText(restTemplate)) {

View File

@@ -56,6 +56,7 @@ import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
@@ -76,9 +77,15 @@ import org.springframework.web.client.RestTemplate;
*/
public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMessageHandler {
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
private final RestTemplate restTemplate;
private final StandardEvaluationContext evaluationContext;
private final Expression uriExpression;
private volatile HttpMethod httpMethod = HttpMethod.POST;
private volatile Expression httpMethodExpression = new LiteralExpression(HttpMethod.POST.name());
private volatile boolean expectReply = true;
@@ -94,12 +101,6 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
private volatile HeaderMapper<HttpHeaders> headerMapper = DefaultHttpHeaderMapper.outboundMapper();
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
private final RestTemplate restTemplate;
private final StandardEvaluationContext evaluationContext;
/**
* Create a handler that will send requests to the provided URI.
*/
@@ -152,12 +153,21 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
this.evaluationContext = sec;
}
/**
* Specify the SpEL {@link Expression} to determine {@link HttpMethod} dynamically
*
* @param httpMethodExpression
*/
public void setHttpMethodExpression(Expression httpMethodExpression) {
Assert.notNull(httpMethodExpression, "'httpMethodExpression' must not be null");
this.httpMethodExpression = httpMethodExpression;
}
/**
* Specify the {@link HttpMethod} for requests. The default method will be POST.
*/
public void setHttpMethod(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
this.httpMethodExpression = new LiteralExpression(httpMethod.name());
}
/**
@@ -262,12 +272,6 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
if (conversionService != null) {
this.evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
}
if (!this.shouldIncludeRequestBody() && this.extractPayloadExplicitlySet){
if (logger.isWarnEnabled()){
logger.warn("The 'extractPayload' attribute has no meaning in the context of this handler since the provided HTTP Method is '" +
this.httpMethod + "', and no request body will be sent for that method.");
}
}
}
@Override
@@ -280,8 +284,18 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
Object value = entry.getValue().getValue(this.evaluationContext, requestMessage, String.class);
uriVariables.put(entry.getKey(), value);
}
HttpEntity<?> httpRequest = this.generateHttpRequest(requestMessage);
ResponseEntity<?> httpResponse = this.restTemplate.exchange(uri, this.httpMethod, httpRequest, this.expectedResponseType, uriVariables);
HttpMethod httpMethod = this.determineHttpMethod(requestMessage);
if (!this.shouldIncludeRequestBody(httpMethod) && this.extractPayloadExplicitlySet){
if (logger.isWarnEnabled()){
logger.warn("The 'extractPayload' attribute has no relevance for the current request since the HTTP Method is '" +
httpMethod + "', and no request body will be sent for that method.");
}
}
HttpEntity<?> httpRequest = this.generateHttpRequest(requestMessage, httpMethod);
ResponseEntity<?> httpResponse = this.restTemplate.exchange(uri, httpMethod, httpRequest, this.expectedResponseType, uriVariables);
if (this.expectReply) {
HttpHeaders httpHeaders = httpResponse.getHeaders();
Map<String, Object> headers = this.headerMapper.toHeaders(httpHeaders);
@@ -332,20 +346,20 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
}
private HttpEntity<?> generateHttpRequest(Message<?> message) throws Exception {
private HttpEntity<?> generateHttpRequest(Message<?> message, HttpMethod httpMethod) throws Exception {
Assert.notNull(message, "message must not be null");
return (this.extractPayload) ? this.createHttpEntityFromPayload(message)
: this.createHttpEntityFromMessage(message);
return (this.extractPayload) ? this.createHttpEntityFromPayload(message, httpMethod)
: this.createHttpEntityFromMessage(message, httpMethod);
}
private HttpEntity<?> createHttpEntityFromPayload(Message<?> message) {
private HttpEntity<?> createHttpEntityFromPayload(Message<?> message, HttpMethod httpMethod) {
Object payload = message.getPayload();
if (payload instanceof HttpEntity<?>) {
// payload is already an HttpEntity, just return it as-is
return (HttpEntity<?>) payload;
}
HttpHeaders httpHeaders = this.mapHeaders(message);
if (!shouldIncludeRequestBody()) {
if (!shouldIncludeRequestBody(httpMethod)) {
return new HttpEntity<Object>(httpHeaders);
}
// otherwise, we are creating a request with a body and need to deal with the content-type header as well
@@ -363,9 +377,9 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
return new HttpEntity<Object>(payload, httpHeaders);
}
private HttpEntity<?> createHttpEntityFromMessage(Message<?> message) {
private HttpEntity<?> createHttpEntityFromMessage(Message<?> message, HttpMethod httpMethod) {
HttpHeaders httpHeaders = mapHeaders(message);
if (shouldIncludeRequestBody()) {
if (shouldIncludeRequestBody(httpMethod)) {
httpHeaders.setContentType(new MediaType("application", "x-java-serialized-object"));
return new HttpEntity<Object>(message, httpHeaders);
}
@@ -405,8 +419,8 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
return contentType;
}
private boolean shouldIncludeRequestBody() {
return !HttpMethod.GET.equals(this.httpMethod);
private boolean shouldIncludeRequestBody(HttpMethod httpMethod) {
return !HttpMethod.GET.equals(httpMethod);
}
private MediaType resolveContentType(String content, String charset) {
@@ -470,4 +484,10 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
return true;
}
private HttpMethod determineHttpMethod(Message<?> requestMessage) {
String strHttpMethod = httpMethodExpression.getValue(this.evaluationContext, requestMessage, String.class);
Assert.isTrue(StringUtils.hasText(strHttpMethod) && !Arrays.asList(HttpMethod.values()).contains(strHttpMethod),
"The 'httpMethodExpression' returned an invalid HTTP Method value: " + strHttpMethod);
return HttpMethod.valueOf(strHttpMethod);
}
}

View File

@@ -360,16 +360,25 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="http-method" default="POST">
<xsd:attribute name="http-method">
<xsd:annotation>
<xsd:documentation>
The HTTP method to use when executing requests with this adapter.
The HTTP method to use when executing requests with this adapter Default is POST.
This attribute cannot be provided if http-method-expression has a value.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="httpMethodEnumeration xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="http-method-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The SpEL expression to determine HTTP method, use when executing requests with this adapter,
dynamically. This attribute cannot be provided if http-method has a value.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
@@ -499,16 +508,25 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="http-method" default="POST">
<xsd:attribute name="http-method">
<xsd:annotation>
<xsd:documentation>
The HTTP method to use when executing requests with this adapter.
The HTTP method to use when executing requests with this adapter. Default is POST.
This attribute cannot be provided if http-method-expression has a value.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="httpMethodEnumeration xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="http-method-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The SpEL expression to determine HTTP method, use when executing requests with this gateway,
dynamically. This attribute cannot be provided if http-method has a value.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="message-converters" type="xsd:string">
<xsd:annotation>
<xsd:documentation>

View File

@@ -28,6 +28,7 @@ import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -98,7 +99,7 @@ public class HttpOutboundChannelAdapterParserTests {
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
assertEquals("http://localhost/test1", uriExpression.getValue());
assertEquals(HttpMethod.POST, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
}
@@ -127,7 +128,7 @@ public class HttpOutboundChannelAdapterParserTests {
assertEquals(errorHandlerBean, templateAccessor.getPropertyValue("errorHandler"));
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
assertEquals("http://localhost/test2/{foo}", uriExpression.getValue());
assertEquals(HttpMethod.GET, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.GET.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(false, handlerAccessor.getPropertyValue("extractPayload"));
Map<String, Expression> uriVariableExpressions =
@@ -172,7 +173,7 @@ public class HttpOutboundChannelAdapterParserTests {
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
assertEquals("http://localhost/test1", uriExpression.getValue());
assertEquals(HttpMethod.POST, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
}
@@ -195,7 +196,7 @@ public class HttpOutboundChannelAdapterParserTests {
SpelExpression expression = (SpelExpression) handlerAccessor.getPropertyValue("uriExpression");
assertNotNull(expression);
assertEquals("'http://localhost/test1'", expression.getExpressionString());
assertEquals(HttpMethod.POST, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
}
@@ -218,7 +219,7 @@ public class HttpOutboundChannelAdapterParserTests {
SpelExpression expression = (SpelExpression) handlerAccessor.getPropertyValue("uriExpression");
assertNotNull(expression);
assertEquals("'http://localhost/test1'", expression.getExpressionString());
assertEquals(HttpMethod.POST, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
}

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -39,6 +40,7 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
@@ -80,7 +82,7 @@ public class HttpOutboundGatewayParserTests {
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
assertEquals("http://localhost/test1", uriExpression.getValue());
assertEquals(HttpMethod.POST, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
assertEquals(false, handlerAccessor.getPropertyValue("transferCookies"));
@@ -109,7 +111,7 @@ public class HttpOutboundGatewayParserTests {
assertEquals(String.class, handlerAccessor.getPropertyValue("expectedResponseType"));
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
assertEquals("http://localhost/test2", uriExpression.getValue());
assertEquals(HttpMethod.PUT, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.PUT.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(false, handlerAccessor.getPropertyValue("extractPayload"));
Object requestFactoryBean = this.applicationContext.getBean("testRequestFactory");
@@ -151,7 +153,7 @@ public class HttpOutboundGatewayParserTests {
SpelExpression expression = (SpelExpression) handlerAccessor.getPropertyValue("uriExpression");
assertNotNull(expression);
assertEquals("'http://localhost/test1'", expression.getExpressionString());
assertEquals(HttpMethod.POST, handlerAccessor.getPropertyValue("httpMethod"));
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
assertEquals(false, handlerAccessor.getPropertyValue("transferCookies"));

View File

@@ -0,0 +1,125 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.message.GenericMessage;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
/**
* @author Oleg Zhurakousky
*
* see https://jira.springsource.org/browse/INT-2397
*/
public class HttpOutboundGatewayWithMethodExpression {
private HttpServer server;
private MyHandler httpHandler;
@Before
public void createServer() throws Exception {
httpHandler = new MyHandler();
server = HttpServer.create(new InetSocketAddress(51234), 0);
server.createContext("/testApps/httpMethod", httpHandler);
server.start();
}
@After
public void stopServer() throws Exception {
server.stop(0);
}
@Test
public void testDefaultMethod() throws Exception{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"http-outbound-gateway-with-httpmethod-expression.xml", this.getClass());
MessageChannel channel = context.getBean("defaultChannel", MessageChannel.class);
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
httpHandler.setHttpMethod("POST");
channel.send(new GenericMessage<String>("Hello"));
Message<?> message = replyChannel.receive(5000);
assertNotNull(message);
assertEquals("POST", message.getPayload());
}
@Test
public void testExplicitlySetMethod() throws Exception{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"http-outbound-gateway-with-httpmethod-expression.xml", this.getClass());
MessageChannel channel = context.getBean("requestChannel", MessageChannel.class);
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
httpHandler.setHttpMethod("GET");
channel.send(new GenericMessage<String>("GET"));
Message<?> message = replyChannel.receive(5000);
assertNotNull(message);
assertEquals("GET", message.getPayload());
}
@Test(expected=BeanDefinitionParsingException.class)
public void testMutuallyExclusivityInMethodAndMethodExpression() throws Exception{
new ClassPathXmlApplicationContext(
"http-outbound-gateway-with-httpmethod-expression-fail.xml", this.getClass());
}
class MyHandler implements HttpHandler {
private String httpMethod;
public void setHttpMethod(String httpMethod){
this.httpMethod = httpMethod;
}
public void handle(HttpExchange t) throws IOException {
String requestMethod = t.getRequestMethod();
String response = null;
if (requestMethod.equalsIgnoreCase(this.httpMethod)){
response = httpMethod;
t.sendResponseHeaders(200, response.length());
}
else {
response = "Request is NOT valid";
t.sendResponseHeaders(404, 0);
}
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}

View File

@@ -0,0 +1,23 @@
<?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:51234/testApps/httpMethod"
request-channel="requestChannel"
reply-channel="replyChannel"
expected-response-type="java.lang.String"
http-method-expression="payload"
http-method="GET"/>
<int:channel id="replyChannel">
<int:queue/>
</int:channel>
</beans>

View File

@@ -0,0 +1,26 @@
<?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:51234/testApps/httpMethod"
request-channel="requestChannel"
reply-channel="replyChannel"
expected-response-type="java.lang.String"
http-method-expression="payload"/>
<int-http:outbound-gateway url="http://localhost:51234/testApps/httpMethod"
request-channel="defaultChannel"
reply-channel="replyChannel"
expected-response-type="java.lang.String"/>
<int:channel id="replyChannel">
<int:queue/>
</int:channel>
</beans>

View File

@@ -30,7 +30,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.integration.Message;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.message.GenericMessage;
/**
@@ -47,6 +46,7 @@ public class UriVariableExpressionTests {
SpelExpressionParser parser = new SpelExpressionParser();
handler.setUriVariableExpressions(Collections.singletonMap("foo", parser.parseExpression("payload")));
handler.setRequestFactory(new SimpleClientHttpRequestFactory() {
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
uriHolder.set(uri);
throw new RuntimeException("intentional");

View File

@@ -265,6 +265,20 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
of the HTTP Outbound Gateway was renamed to <emphasis>reply-timeout</emphasis>
to better reflect the intent.
</important>
<para>
Beginning with Spring Integration 2.2 you can also determine the HTTP Method dynamically using SpEL and the <emphasis>http-method-expression</emphasis> attribute.
Note that this attribute is obviously murually exclusive with <emphasis>http-method</emphasis>
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway id="example"
request-channel="requests"
url="http://localhost/test"
http-method-expression="headers.httpMethod"
extract-request-payload="false"
expected-response-type="java.lang.String"
charset="UTF-8"
request-factory="requestFactory"
reply-timeout="1234"
reply-channel="replies"/>]]></programlisting>
</para>
<para>If your outbound adapter is to be used in a unidirectional way, then you can use an outbound-channel-adapter instead. This means that
a successful response will simply execute without sending any Messages to a reply channel. In the case of any non-successful response
status code, it will throw an exception. The configuration looks very similar to the gateway: