From 6bbe8057abb03c621279eb91b4715088ce0c36d0 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 6 Jun 2012 12:33:34 -0400 Subject: [PATCH] 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. --- .../http/config/HttpAdapterParsingUtils.java | 26 +++ .../HttpOutboundChannelAdapterParser.java | 2 +- .../config/HttpOutboundGatewayParser.java | 4 +- .../HttpRequestExecutingMessageHandler.java | 56 ++++++- .../config/spring-integration-http-2.2.xsd | 28 +++- ...HttpOutboundChannelAdapterParserTests.java | 4 +- .../HttpOutboundGatewayParserTests.java | 5 +- ...OutboundResponseTypeTests-context-fail.xml | 22 +++ .../OutboundResponseTypeTests-context.xml | 29 ++++ .../config/OutboundResponseTypeTests.java | 154 ++++++++++++++++++ ...tpRequestExecutingMessageHandlerTests.java | 9 +- src/reference/docbook/http.xml | 8 +- 12 files changed, 320 insertions(+), 27 deletions(-) create mode 100644 spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context-fail.xml create mode 100644 spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml create mode 100644 spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java index bd317eca5c..93afd42e17 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java @@ -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); + } + } + } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java index f86391ece1..df81521391 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java @@ -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(); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java index 7289cdb0c7..0d13e685ec 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java @@ -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); diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java index b65fe78525..62f79383ed 100755 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java @@ -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, 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 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; + } } diff --git a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd index ab42e738ee..cdbf33b3c1 100644 --- a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd +++ b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd @@ -411,7 +411,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re - 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 @@ -420,6 +422,16 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re + + + + 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 + + + @@ -595,7 +607,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re - 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 @@ -604,6 +618,16 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re + + + + 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 + + + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java index d3cb1356fb..0b93513d47 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java @@ -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. @@ -118,7 +118,7 @@ public class HttpOutboundChannelAdapterParserTests { 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")); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java index e5e29f9010..f70be245bb 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java @@ -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. @@ -108,7 +108,8 @@ public class HttpOutboundGatewayParserTests { 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()); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context-fail.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context-fail.xml new file mode 100644 index 0000000000..925fdc56fd --- /dev/null +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context-fail.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml new file mode 100644 index 0000000000..dae66323b5 --- /dev/null +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java new file mode 100644 index 0000000000..a40b10cf1e --- /dev/null +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java @@ -0,0 +1,154 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.http.ResponseEntity; +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 OutboundResponseTypeTests { + + private static HttpServer server; + private static MyHandler httpHandler; + + @BeforeClass + public static void createServer() throws Exception { + httpHandler = new MyHandler(); + server = HttpServer.create(new InetSocketAddress(51235), 0); + server.createContext("/testApps/outboundResponse", httpHandler); + server.start(); + } + @AfterClass + public static void stopServer() throws Exception { + server.stop(0); + } + + @Test + public void testDefaultResponseType() throws Exception{ + + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "OutboundResponseTypeTests-context.xml", this.getClass()); + + MessageChannel channel = context.getBean("requestChannel", MessageChannel.class); + QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class); + + channel.send(new GenericMessage("Hello")); + Message message = replyChannel.receive(5000); + assertNotNull(message); + assertTrue(message.getPayload() instanceof ResponseEntity); + } + + @Test + public void testWithResponseTypeSet() throws Exception{ + + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "OutboundResponseTypeTests-context.xml", this.getClass()); + + MessageChannel channel = context.getBean("resTypeSetChannel", MessageChannel.class); + QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class); + + channel.send(new GenericMessage("Hello")); + Message message = replyChannel.receive(5000); + assertNotNull(message); + assertTrue(message.getPayload() instanceof String); + } + + @Test + public void testWithResponseTypeExpressionSet() throws Exception{ + + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "OutboundResponseTypeTests-context.xml", this.getClass()); + + MessageChannel channel = context.getBean("resTypeExpressionSetChannel", MessageChannel.class); + QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class); + + channel.send(new GenericMessage("java.lang.String")); + Message message = replyChannel.receive(5000); + assertNotNull(message); + assertTrue(message.getPayload() instanceof String); + } + + @Test + public void testWithResponseTypeExpressionSetAsClass() throws Exception{ + + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "OutboundResponseTypeTests-context.xml", this.getClass()); + + MessageChannel channel = context.getBean("resTypeExpressionSetChannel", MessageChannel.class); + QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class); + + channel.send(new GenericMessage>(String.class)); + Message message = replyChannel.receive(5000); + assertNotNull(message); + assertTrue(message.getPayload() instanceof String); + } + + @Test(expected=BeanDefinitionParsingException.class) + public void testMutuallyExclusivityInMethodAndMethodExpression() throws Exception{ + + new ClassPathXmlApplicationContext( + "OutboundResponseTypeTests-context-fail.xml", this.getClass()); + } + + static class MyHandler implements HttpHandler { + private String httpMethod = "POST"; + + 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(); + } + } +} diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java index 45ed14907c..a8cb14cdc3 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java @@ -22,9 +22,6 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -34,10 +31,6 @@ import java.util.concurrent.atomic.AtomicReference; import javax.xml.transform.Source; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import org.junit.Assert; import org.junit.Test; import org.springframework.beans.DirectFieldAccessor; import org.springframework.context.ApplicationContext; @@ -671,7 +664,7 @@ public class HttpRequestExecutingMessageHandlerTests { PollableChannel output = ctx.getBean("replyChannel", PollableChannel.class); Message receive = output.receive(); - assertEquals(HttpStatus.OK, receive.getPayload()); + assertEquals(HttpStatus.OK, ((ResponseEntity)receive.getPayload()).getStatusCode()); } diff --git a/src/reference/docbook/http.xml b/src/reference/docbook/http.xml index 118eaef679..d9ef6bc8b8 100644 --- a/src/reference/docbook/http.xml +++ b/src/reference/docbook/http.xml @@ -246,8 +246,8 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w To configure the outbound gateway you can use the namespace support as well. The following code snippet shows the different configuration options for an outbound Http gateway. Most importantly, notice that the 'http-method' and 'expected-response-type' are provided. Those are two of the most commonly configured values. The - default http-method is POST, and the default response type is null. With a null response type, the payload of the reply Message would only - contain the status code (e.g. 200) as long as it's a successful status (non-successful status codes will throw Exceptions). If you are expecting a different + default http-method is POST, and the default response type is null. With a null response type, the payload of the reply Message would + contain the ResponseEntity as long as it's http status is a success (non-successful status codes will throw Exceptions). If you are expecting a different type, such as a String, then provide that fully-qualified class name as shown below. Beginning with Spring Integration 2.2 you can also determine the HTTP Method dynamically using SpEL and the http-method-expression attribute. Note that this attribute is obviously murually exclusive with http-method + You can also use expected-response-type-expression attribute instead of expected-response-type and + provide any valid SpEL expression that determines the type of the response.