diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java
index 0ad7faf5ff..aaf11db599 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java
@@ -176,6 +176,12 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
builder.addPropertyValue("requestMapping", requestMappingDef);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-payload-type", "requestPayloadType");
+
+ BeanDefinition statusCodeExpressionDef =
+ IntegrationNamespaceUtils.createExpressionDefIfAttributeDefined("status-code-expression", element);
+ if (statusCodeExpressionDef != null) {
+ builder.addPropertyValue("statusCodeExpression", statusCodeExpressionDef);
+ }
}
private String getInputChannelAttributeName() {
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java
index 059ca4778d..e8234bf342 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java
@@ -51,6 +51,7 @@ import org.springframework.web.servlet.mvc.Controller;
*
* @author Mark Fisher
* @author Gary Russell
+ * @author Artem Bilan
* @since 2.0
*/
public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSupport implements Controller {
@@ -148,12 +149,16 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
ModelAndView modelAndView = new ModelAndView();
try {
Message> replyMessage = super.doHandleRequest(servletRequest, servletResponse);
+ ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
if (replyMessage != null) {
- ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
Object reply = setupResponseAndConvertReply(response, replyMessage);
response.close();
modelAndView.addObject(this.replyKey, reply);
}
+ else {
+ setStatusCodeIfNeeded(response);
+ }
+
if (this.viewExpression != null) {
Object view;
if (replyMessage != null) {
@@ -184,4 +189,5 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
}
return modelAndView;
}
+
}
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java
index 86971a85cf..0193943e9e 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java
@@ -31,6 +31,7 @@ import javax.xml.transform.Source;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.http.HttpEntity;
@@ -151,6 +152,10 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
private volatile boolean shuttingDown;
+ private volatile Expression statusCodeExpression;
+
+ private volatile EvaluationContext evaluationContext;
+
private final AtomicInteger activeCount = new AtomicInteger();
public HttpRequestHandlingEndpointSupport() {
@@ -315,6 +320,19 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
this.multipartResolver = multipartResolver;
}
+ /**
+ * Specify the {@link Expression} to resolve a status code for Response
+ * to override the default '200 OK'.
+ *
The {@link #statusCodeExpression} is applied only for the one-way {@code }.
+ * The {@code } resolves an {@link HttpStatus} from the
+ * {@link org.springframework.integration.http.HttpHeaders#STATUS_CODE} reply {@link Message} header.
+ * @param statusCodeExpression The status code Expression.
+ * @since 4.1
+ */
+ public void setStatusCodeExpression(Expression statusCodeExpression) {
+ this.statusCodeExpression = statusCodeExpression;
+ }
+
@Override
public String getComponentType() {
return (this.expectReply) ? "http:inbound-gateway" : "http:inbound-channel-adapter";
@@ -351,6 +369,15 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
this.messageConverters.addAll(this.defaultMessageConverters);
}
this.validateSupportedMethods();
+
+ if (this.expectReply && this.statusCodeExpression != null) {
+ logger.warn("The 'statusCodeExpression' is ignored when " +
+ "this component is configured as request/reply gateway");
+ }
+
+ if (this.statusCodeExpression != null) {
+ this.evaluationContext = createEvaluationContext();
+ }
}
/**
@@ -515,6 +542,19 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
}
+ protected void setStatusCodeIfNeeded(ServletServerHttpResponse response) {
+ if (this.statusCodeExpression != null) {
+ if (this.evaluationContext == null) {
+ this.evaluationContext = createEvaluationContext();
+ }
+ Object value = this.statusCodeExpression.getValue(this.evaluationContext);
+ HttpStatus httpStatus = buildHttpStatus(value);
+ if (httpStatus != null) {
+ response.setStatusCode(httpStatus);
+ }
+ }
+ }
+
/**
* Prepares an instance of {@link ServletServerHttpRequest} from the raw
* {@link HttpServletRequest}. Also converts the request into a multipart request to
@@ -586,15 +626,19 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
private HttpStatus resolveHttpStatusFromHeaders(MessageHeaders headers) {
Object httpStatusFromHeader = headers.get(org.springframework.integration.http.HttpHeaders.STATUS_CODE);
+ return buildHttpStatus(httpStatusFromHeader);
+ }
+
+ private HttpStatus buildHttpStatus(Object httpStatusValue) {
HttpStatus httpStatus = null;
- if (httpStatusFromHeader instanceof HttpStatus) {
- httpStatus = (HttpStatus) httpStatusFromHeader;
+ if (httpStatusValue instanceof HttpStatus) {
+ httpStatus = (HttpStatus) httpStatusValue;
}
- else if (httpStatusFromHeader instanceof Integer) {
- httpStatus = HttpStatus.valueOf((Integer) httpStatusFromHeader);
+ else if (httpStatusValue instanceof Integer) {
+ httpStatus = HttpStatus.valueOf((Integer) httpStatusValue);
}
- else if (httpStatusFromHeader instanceof String) {
- httpStatus = HttpStatus.valueOf(Integer.parseInt((String) httpStatusFromHeader));
+ else if (httpStatusValue instanceof String) {
+ httpStatus = HttpStatus.valueOf(Integer.parseInt((String) httpStatusValue));
}
return httpStatus;
}
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java
index 4ddbafdd52..5feaa0a6ce 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -57,9 +57,11 @@ import org.springframework.web.HttpRequestHandler;
*
* @author Mark Fisher
* @author Oleg Zhurakousky
+ * @author Artem Bilan
* @since 2.0
*/
-public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndpointSupport implements HttpRequestHandler {
+public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndpointSupport
+ implements HttpRequestHandler {
private volatile boolean convertExceptions;
@@ -115,6 +117,9 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
this.writeResponse(responseContent, response, request.getHeaders().getAccept());
}
}
+ else {
+ setStatusCodeIfNeeded(response);
+ }
}
private Object handleExceptionInternal(Exception e) throws IOException {
@@ -135,7 +140,8 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
}
@SuppressWarnings({"unchecked", "rawtypes"})
- private void writeResponse(Object content, ServletServerHttpResponse response, List acceptTypes) throws IOException {
+ private void writeResponse(Object content, ServletServerHttpResponse response, List acceptTypes)
+ throws IOException {
if (CollectionUtils.isEmpty(acceptTypes)) {
acceptTypes = Collections.singletonList(MediaType.ALL);
}
diff --git a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-4.1.xsd b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-4.1.xsd
index 4041a7c196..7d4b1aa857 100644
--- a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-4.1.xsd
+++ b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-4.1.xsd
@@ -52,6 +52,23 @@
+
+
+
+ A SpEL expression that resolves to an 'HttpStatus' code when rendering a response.
+ The expression must return the object which can be converted to a
+ 'org.springframework.http.HttpStatus' enum value.
+ The 'evaluationContext' has a 'BeanResolver' but no variables, so the usage of this attribute
+ is somewhat limited.
+ An example might be to resolve, at runtime, some scoped Bean that returns an
+ 'HttpStatus' value.
+ By default 'status-code-expression' is null, meaning that the default '200 OK' response status
+ will be returned.
+ The 'http:inbound-gateway' resolves the 'status code' from the 'http_statusCode' header of the reply
+ Message.
+
+
+
@@ -211,7 +228,7 @@
The expression can resolve to a view name or View object.
In the case of 'inbound-gateway' the root object of the evaluation context is the reply message.
In the case of 'inbound-channel-adapter' the 'evaluationContext' for this expression
- is rather lightweight, because there is no reply message, ; it has a
+ is rather lightweight, because there is no reply message, it has a
'BeanResolver' but no variables,
so the usage of this attribute is somewhat limited.
An example might be to resolve, at runtime, some scoped Bean that returns a
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests-context.xml
index 03487727c8..80b00e77c0 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests-context.xml
@@ -20,7 +20,8 @@
-
+
@@ -38,7 +39,8 @@
-
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java
index 5745e06bed..18c1b87aa1 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -128,7 +128,7 @@ public class HttpInboundChannelAdapterParserTests extends AbstractHttpInboundTes
request.setParameter("foo", "bar");
MockHttpServletResponse response = new MockHttpServletResponse();
defaultAdapter.handleRequest(request, response);
- assertEquals(HttpServletResponse.SC_OK, response.getStatus());
+ assertEquals(HttpServletResponse.SC_SWITCHING_PROTOCOLS, response.getStatus());
Message> message = requests.receive(0);
assertNotNull(message);
Object payload = message.getPayload();
@@ -256,6 +256,15 @@ public class HttpInboundChannelAdapterParserTests extends AbstractHttpInboundTes
assertEquals("oops", errorCode);
Expression viewExpression = TestUtils.getPropertyValue(inboundController, "viewExpression", Expression.class);
assertEquals("foo", viewExpression.getExpressionString());
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setMethod("GET");
+ request.setParameter("foo", "bar");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ inboundController.handleRequest(request, response);
+ assertEquals(HttpServletResponse.SC_ACCEPTED, response.getStatus());
+ Message> message = requests.receive(0);
+ assertNotNull(message);
}
@Test
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java
index 7ef211cbdb..34f007a769 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -31,6 +31,7 @@ import java.util.List;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
+import org.springframework.expression.common.LiteralExpression;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
@@ -116,6 +117,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
}
});
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
+ gateway.setStatusCodeExpression(new LiteralExpression("foo"));
gateway.setBeanFactory(mock(BeanFactory.class));
gateway.setRequestPayloadType(String.class);
gateway.setRequestChannel(requestChannel);
diff --git a/src/reference/docbook/http.xml b/src/reference/docbook/http.xml
index e1d3e8b2fc..842eb92330 100644
--- a/src/reference/docbook/http.xml
+++ b/src/reference/docbook/http.xml
@@ -317,6 +317,29 @@ By default the HTTP request will be generated using an instance of Si
+ Response StatusCode
+
+ Starting with version 4.1 the <http:inbound-channel-adapter>
+ can be configured with a status-code-expression to override the default 200 OK status.
+ The expression must return an object which can be converted to a
+ org.springframework.http.HttpStatus enum value.
+ The evaluationContext has a BeanResolver but no variables,
+ so the usage of this attribute is somewhat limited.
+ An example might be to resolve, at runtime, some scoped Bean that returns a status code value but,
+ most likely, it will be set to a fixed value
+ such as status-code=expression="'204'" (No Content), or
+ status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT".
+ By default, status-code-expression is null meaning that the normal '200 OK' response status
+ will be returned.
+
+
+]]>
+ The <http:inbound-gateway> resolves the 'status code' from the http_statusCode
+ header of the reply Message.
+
+
URI Template Variables and Expressions
By Using the path attribute in conjunction with the
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml
index c16602b624..9dace90410 100644
--- a/src/reference/docbook/whats-new.xml
+++ b/src/reference/docbook/whats-new.xml
@@ -46,5 +46,13 @@
before sending the request.
+
+ Http Inbound Channel Adapter and StatusCode
+
+ The <http:inbound-channel-adapter> can now be configured with a
+ status-code-expression to override the default 200 OK status.
+ See for more information.
+
+