INT-3781: Configure HTTP GW Timeout Status Code

JIRA: https://jira.spring.io/browse/INT-3781

- Add mechanisms to set status code on an inbound gateway timeout.
- Send a message to the error channel if configured.

Polishing - Add failedMessage to MTE

Fix Schema Docs; Timeout Detection on Error Flow

Add Zookeeper Leadership Logs

Fix typo in the `SmartLifecycleRoleController`
This commit is contained in:
Gary Russell
2015-07-24 13:02:58 -04:00
committed by Artem Bilan
parent 178c86faa4
commit 9944e54ce5
9 changed files with 256 additions and 32 deletions

View File

@@ -195,6 +195,10 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
BeanDefinition statusCodeExpressionDef =
IntegrationNamespaceUtils.createExpressionDefIfAttributeDefined("status-code-expression", element);
if (statusCodeExpressionDef == null) {
statusCodeExpressionDef = IntegrationNamespaceUtils
.createExpressionDefIfAttributeDefined("reply-timeout-status-code-expression", element);
}
if (statusCodeExpressionDef != null) {
builder.addPropertyValue("statusCodeExpression", statusCodeExpressionDef);
}

View File

@@ -50,6 +50,7 @@ import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConvert
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.integration.MessageTimeoutException;
import org.springframework.integration.context.OrderlyShutdownCapable;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.gateway.MessagingGatewaySupport;
@@ -122,6 +123,8 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
private final List<HttpMessageConverter<?>> defaultMessageConverters = new ArrayList<HttpMessageConverter<?>>();
private final boolean expectReply;
private volatile List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
private volatile RequestMapping requestMapping = new RequestMapping();
@@ -136,8 +139,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
private volatile HeaderMapper<HttpHeaders> headerMapper = DefaultHttpHeaderMapper.inboundMapper();
private final boolean expectReply;
private volatile boolean extractReplyPayload = true;
private volatile MultipartResolver multipartResolver;
@@ -159,6 +160,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
}
public HttpRequestHandlingEndpointSupport(boolean expectReply) {
super(expectReply);
this.expectReply = expectReply;
this.defaultMessageConverters.add(new MultipartAwareFormHttpMessageConverter());
this.defaultMessageConverters.add(new ByteArrayHttpMessageConverter());
@@ -331,7 +333,8 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
/**
* Specify the {@link Expression} to resolve a status code for Response
* to override the default '200 OK'.
* <p> The {@link #statusCodeExpression} is applied only for the one-way {@code <http:inbound-channel-adapter/>}.
* <p> The {@link #statusCodeExpression} is applied only for the one-way {@code <http:inbound-channel-adapter/>}
* or when no reply (timeout) is received for a gateway.
* The {@code <http:inbound-gateway/>} resolves an {@link HttpStatus} from the
* {@link org.springframework.integration.http.HttpHeaders#STATUS_CODE} reply {@link Message} header.
* @param statusCodeExpression The status code Expression.
@@ -378,11 +381,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
}
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();
}
@@ -505,7 +503,23 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
Message<?> reply = null;
if (this.expectReply) {
reply = this.sendAndReceiveMessage(message);
try {
reply = this.sendAndReceiveMessage(message);
}
catch (MessageTimeoutException e) {
if (this.statusCodeExpression != null) {
reply = getMessageBuilderFactory().withPayload(e.getMessage())
.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE,
evaluateHttpStatus())
.build();
}
else {
reply = getMessageBuilderFactory().withPayload(e.getMessage())
.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE,
HttpStatus.INTERNAL_SERVER_ERROR)
.build();
}
}
}
else {
this.send(message);
@@ -552,17 +566,22 @@ 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);
HttpStatus httpStatus = evaluateHttpStatus();
if (httpStatus != null) {
response.setStatusCode(httpStatus);
}
}
}
private HttpStatus evaluateHttpStatus() {
if (this.evaluationContext == null) {
this.evaluationContext = createEvaluationContext();
}
Object value = this.statusCodeExpression.getValue(this.evaluationContext);
HttpStatus httpStatus = buildHttpStatus(value);
return httpStatus;
}
/**
* Prepares an instance of {@link ServletServerHttpRequest} from the raw
* {@link HttpServletRequest}. Also converts the request into a multipart request to

View File

@@ -63,12 +63,12 @@
<xsd:annotation>
<xsd:documentation>
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
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 an
'HttpStatus' value.
'HttpStatus' value, or use a literal expression e.g. "201".
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
@@ -203,6 +203,25 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-timeout-status-code-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression that resolves to an 'HttpStatus' code when rendering a response after
a 'reply-timeout'.
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 an
'HttpStatus' value, or use a literal expression e.g. "504".
By default 'status-code-expression' is null, meaning that the default
'500 Internal Server Error' response status will be returned after a timeout.
When a timeout is not encountered,
the 'http:inbound-gateway' resolves the 'status code' from the 'http_statusCode' header of the reply
Message.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>