INT-3933: HTTP & WS Inbound Lifecycle Handling

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

Previously the HTTP and WS Inbound Endpoint haven't handled the `stopped` state properly.

* Add `lifecycle` parsing to the `HttpInboundEndpointParser`
* Handle `!isRunning()` state and throw an appropriate `503 Service Unavailable` HTTP response
* Expose `lifecycle` options for the `<int-ws:inbound-gateway>`
* Introduce `ServiceUnavailableException` `WebServiceException` to indicate `stopped` state for the WS Inbound Endpoint
* Fix tests for the new logic

INT-3933: PR comments: `OrderlyShutdownCapable` for `AbstractWebServiceInboundGateway`
This commit is contained in:
Artem Bilan
2016-01-18 16:09:11 -05:00
committed by Gary Russell
parent c97afe92fe
commit c0784bf6ef
18 changed files with 216 additions and 72 deletions

View File

@@ -21,6 +21,8 @@
</si:channel>
<inbound-channel-adapter id="defaultAdapter" channel="requests" error-channel="errorChannel"
auto-startup="false"
phase="1001"
status-code-expression="'101'"/>
<inbound-channel-adapter id="postOnlyAdapter" path="/postOnly" channel="requests" supported-methods="POST"/>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -123,11 +124,17 @@ public class HttpInboundChannelAdapterParserTests extends AbstractHttpInboundTes
@Test
@SuppressWarnings("unchecked")
public void getRequestOk() throws Exception {
assertFalse(TestUtils.getPropertyValue(this.defaultAdapter, "autoStartup", Boolean.class));
assertEquals(1001, TestUtils.getPropertyValue(this.defaultAdapter, "phase"));
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setParameter("foo", "bar");
MockHttpServletResponse response = new MockHttpServletResponse();
defaultAdapter.handleRequest(request, response);
this.defaultAdapter.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_SERVICE_UNAVAILABLE, response.getStatus());
this.defaultAdapter.start();
response = new MockHttpServletResponse();
this.defaultAdapter.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_SWITCHING_PROTOCOLS, response.getStatus());
Message<?> message = requests.receive(0);
assertNotNull(message);
@@ -138,7 +145,7 @@ public class HttpInboundChannelAdapterParserTests extends AbstractHttpInboundTes
assertEquals("foo", map.keySet().iterator().next());
assertEquals(1, map.get("foo").size());
assertEquals("bar", map.getFirst("foo"));
assertNotNull(TestUtils.getPropertyValue(defaultAdapter, "errorChannel"));
assertNotNull(TestUtils.getPropertyValue(this.defaultAdapter, "errorChannel"));
}
@Test

View File

@@ -23,6 +23,8 @@
convert-exceptions="true"
request-timeout="1234"
reply-timeout="4567"
auto-startup="false"
phase="1001"
error-channel="errorChannel"/>
<inbound-gateway id="inboundController" request-channel="requests" reply-channel="responses" view-name="foo"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,28 +118,33 @@ public class HttpInboundGatewayParserTests {
@Test
public void checkConfig() {
assertNotNull(gateway);
assertTrue(getPropertyValue(gateway, "expectReply", Boolean.class));
assertTrue(getPropertyValue(gateway, "convertExceptions", Boolean.class));
assertSame(this.responses, getPropertyValue(gateway, "replyChannel"));
assertNotNull(TestUtils.getPropertyValue(gateway, "errorChannel"));
MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(
gateway, "messagingTemplate", MessagingTemplate.class);
assertNotNull(this.gateway);
assertTrue(getPropertyValue(this.gateway, "expectReply", Boolean.class));
assertTrue(getPropertyValue(this.gateway, "convertExceptions", Boolean.class));
assertSame(this.responses, getPropertyValue(this.gateway, "replyChannel"));
assertNotNull(TestUtils.getPropertyValue(this.gateway, "errorChannel"));
MessagingTemplate messagingTemplate =
TestUtils.getPropertyValue(this.gateway, "messagingTemplate", MessagingTemplate.class);
assertEquals(1234L, TestUtils.getPropertyValue(messagingTemplate, "sendTimeout"));
assertEquals(4567L, TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout"));
boolean registerDefaultConverters = TestUtils.getPropertyValue(gateway,"mergeWithDefaultConverters", Boolean.class);
boolean registerDefaultConverters =
TestUtils.getPropertyValue(this.gateway,"mergeWithDefaultConverters", Boolean.class);
assertFalse("By default the register-default-converters flag should be false", registerDefaultConverters);
@SuppressWarnings("unchecked")
List<HttpMessageConverter<?>> messageConverters = TestUtils.getPropertyValue(gateway,"messageConverters", List.class);
List<HttpMessageConverter<?>> messageConverters =
TestUtils.getPropertyValue(this.gateway,"messageConverters", List.class);
assertTrue("The default converters should have been registered, given there are no custom converters",
messageConverters.size() > 0);
assertFalse(TestUtils.getPropertyValue(this.gateway, "autoStartup", Boolean.class));
assertEquals(1001, TestUtils.getPropertyValue(this.gateway, "phase"));
}
@Test @DirtiesContext
public void checkFlow() throws Exception {
requests.subscribe(handlerExpecting(any(Message.class)));
this.requests.subscribe(handlerExpecting(any(Message.class)));
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.addHeader("Accept", "application/x-java-serialized-object");
@@ -148,10 +153,11 @@ public class HttpInboundGatewayParserTests {
MockHttpServletResponse response = new MockHttpServletResponse();
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new SerializingHttpMessageConverter());
gateway.setMessageConverters(converters);
gateway.afterPropertiesSet();
this.gateway.setMessageConverters(converters);
this.gateway.afterPropertiesSet();
this.gateway.start();
gateway.handleRequest(request, response);
this.gateway.handleRequest(request, response);
assertThat(response.getStatus(), is(HttpServletResponse.SC_OK));
assertEquals(response.getContentType(), "application/x-java-serialized-object");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -53,6 +53,7 @@ import org.springframework.web.servlet.View;
* @author Gary Russell
* @author Gunnar Hillert
* @author Biju Kunjummen
* @author Artem Bilan
* @since 2.0
*/
public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests {
@@ -65,6 +66,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
controller.setRequestChannel(requestChannel);
controller.setViewName("foo");
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("hello".getBytes());
@@ -91,6 +94,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
Expression viewExpression = new SpelExpressionParser().parseExpression("'baz'");
controller.setViewExpression(viewExpression);
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("hello".getBytes());
@@ -123,6 +128,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
controller.setRequestChannel(requestChannel);
controller.setViewName("foo");
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
@@ -157,6 +164,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
Expression viewExpression = new SpelExpressionParser().parseExpression("headers['bar']");
controller.setViewExpression(viewExpression);
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("hello".getBytes());
@@ -188,6 +197,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
Expression viewExpression = new SpelExpressionParser().parseExpression("headers['bar']");
controller.setViewExpression(viewExpression);
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("hello".getBytes());
@@ -217,6 +228,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
controller.setViewName("foo");
controller.setReplyKey("myReply");
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("howdy".getBytes());
@@ -250,6 +263,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
controller.setViewName("foo");
controller.setExtractReplyPayload(false);
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("abc".getBytes());
@@ -280,6 +295,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
controller.setBeanFactory(mock(BeanFactory.class));
controller.setRequestChannel(requestChannel);
controller.afterPropertiesSet();
controller.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("hello".getBytes());
@@ -319,6 +336,8 @@ public class HttpRequestHandlingControllerTests extends AbstractHttpInboundTests
controller.setRequestChannel(requestChannel);
controller.setViewName("foo");
controller.afterPropertiesSet();
controller.start();
final MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContent("hello".getBytes());

View File

@@ -76,6 +76,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setBeanFactory(mock(BeanFactory.class));
gateway.setRequestChannel(requestChannel);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setParameter("foo", "bar");
@@ -97,6 +99,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setRequestPayloadType(String.class);
gateway.setRequestChannel(requestChannel);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("text/plain");
@@ -133,6 +137,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setRequestPayloadType(String.class);
gateway.setRequestChannel(requestChannel);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.addHeader("Accept", "x-application/octet-stream");
@@ -159,6 +165,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setRequestPayloadType(String.class);
gateway.setRequestChannel(requestChannel);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("text/plain");
@@ -184,6 +192,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setConvertExceptions(true);
gateway.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList(new TestHttpMessageConverter()));
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "application/x-java-serialized-object");
request.setMethod("GET");
@@ -200,6 +210,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setBeanFactory(mock(BeanFactory.class));
gateway.setRequestChannel(channel);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test");
request.setParameter("foo", "123");
request.addParameter("bar", "456");
@@ -233,6 +245,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
converters.add(new SerializingHttpMessageConverter());
gateway.setMessageConverters(converters);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test");
@@ -281,6 +294,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setBeanFactory(mock(BeanFactory.class));
gateway.setMessageConverters(messageConverters);
gateway.setRequestChannel(requestChannel);
gateway.start();
final MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
@@ -306,6 +320,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setRequestChannel(requestChannel);
gateway.setReplyTimeout(0);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -324,6 +339,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setReplyTimeout(0);
gateway.setStatusCodeExpression(new LiteralExpression("501"));
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -352,6 +369,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
});
gateway.setErrorChannel(errorChannel);
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -372,6 +391,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.setErrorChannel(errorChannel);
gateway.setStatusCodeExpression(new LiteralExpression("501"));
gateway.afterPropertiesSet();
gateway.start();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
MockHttpServletResponse response = new MockHttpServletResponse();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -78,6 +78,7 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
gateway.setRequestMapping(requestMapping);
gateway.afterPropertiesSet();
gateway.start();
gateway.setRequestChannel(echoChannel);
@@ -125,6 +126,7 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
gateway.setRequestChannel(echoChannel);
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables.f"));
gateway.afterPropertiesSet();
gateway.start();
Object result = gateway.doHandleRequest(request, response);
assertTrue(result instanceof Message);
@@ -170,6 +172,7 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
gateway.setRequestChannel(echoChannel);
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables"));
gateway.afterPropertiesSet();
gateway.start();
Object result = gateway.doHandleRequest(request, response);
assertTrue(result instanceof Message);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2016 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.
@@ -63,6 +63,7 @@ public class MultipartAsRawByteArrayTests {
gw.setBeanFactory(mock(BeanFactory.class));
gw.setRequestPayloadType(byte[].class);
gw.afterPropertiesSet();
gw.start();
HttpServletRequest request = mock(HttpServletRequest.class);
ServletInputStream sis = mock(ServletInputStream.class);