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:
committed by
Gary Russell
parent
c97afe92fe
commit
c0784bf6ef
@@ -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.
|
||||
@@ -202,6 +202,9 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
if (statusCodeExpressionDef != null) {
|
||||
builder.addPropertyValue("statusCodeExpression", statusCodeExpressionDef);
|
||||
}
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, IntegrationNamespaceUtils.AUTO_STARTUP);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, IntegrationNamespaceUtils.PHASE);
|
||||
}
|
||||
|
||||
private String getInputChannelAttributeName() {
|
||||
|
||||
@@ -148,8 +148,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
|
||||
private volatile Map<String, Expression> headerExpressions;
|
||||
|
||||
private volatile boolean shuttingDown;
|
||||
|
||||
private volatile Expression statusCodeExpression;
|
||||
|
||||
private volatile EvaluationContext evaluationContext;
|
||||
@@ -397,11 +395,11 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
*/
|
||||
protected final Message<?> doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
|
||||
throws IOException {
|
||||
if (this.isShuttingDown()) {
|
||||
return createServiceUnavailableResponse();
|
||||
if (isRunning()) {
|
||||
return actualDoHandleRequest(servletRequest, servletResponse);
|
||||
}
|
||||
else {
|
||||
return actualDoHandleRequest(servletRequest, servletResponse);
|
||||
return createServiceUnavailableResponse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,9 +534,9 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
|
||||
private Message<?> createServiceUnavailableResponse() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Endpoint is shutting down; returning status " + HttpStatus.SERVICE_UNAVAILABLE);
|
||||
logger.debug("Endpoint is stopped; returning status " + HttpStatus.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
return this.getMessageBuilderFactory().withPayload("Endpoint is shutting down")
|
||||
return this.getMessageBuilderFactory().withPayload("Endpoint is stopped")
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE, HttpStatus.SERVICE_UNAVAILABLE)
|
||||
.build();
|
||||
}
|
||||
@@ -688,22 +686,10 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle
|
||||
*/
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.shuttingDown = false;
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
protected boolean isShuttingDown() {
|
||||
return this.shuttingDown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int beforeShutdown() {
|
||||
this.shuttingDown = true;
|
||||
stop();
|
||||
return this.activeCount.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
<xsd:documentation><![CDATA[
|
||||
Used to set the sendTimeout on the underlying MessagingTemplate instance
|
||||
(org.springframework.integration.core.MessagingTemplate) for sending messages
|
||||
to the request channel. If not specified this propery will default to "1000"
|
||||
to the request channel. If not specified this property will default to "1000"
|
||||
(1 second).
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
@@ -198,7 +198,7 @@
|
||||
<xsd:documentation><![CDATA[
|
||||
Used to set the receiveTimeout on the underlying MessagingTemplate instance
|
||||
(org.springframework.integration.core.MessagingTemplate) for receiving messages
|
||||
from the reply channel. If not specified this propery will default to "1000"
|
||||
from the reply channel. If not specified this property will default to "1000"
|
||||
(1 second).
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -16,8 +16,10 @@
|
||||
package org.springframework.integration.ws;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.integration.context.OrderlyShutdownCapable;
|
||||
import org.springframework.integration.gateway.MessagingGatewaySupport;
|
||||
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -31,9 +33,13 @@ import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
* @since 2.1
|
||||
*/
|
||||
abstract public class AbstractWebServiceInboundGateway extends MessagingGatewaySupport implements MessageEndpoint {
|
||||
public abstract class AbstractWebServiceInboundGateway extends MessagingGatewaySupport
|
||||
implements MessageEndpoint, OrderlyShutdownCapable {
|
||||
|
||||
private final AtomicInteger activeCount = new AtomicInteger();
|
||||
|
||||
protected volatile SoapHeaderMapper headerMapper = new DefaultSoapHeaderMapper();
|
||||
|
||||
@@ -48,9 +54,13 @@ abstract public class AbstractWebServiceInboundGateway extends MessagingGatewayS
|
||||
}
|
||||
|
||||
public void invoke(MessageContext messageContext) throws Exception {
|
||||
if (!isRunning()) {
|
||||
throw new ServiceUnavailableException("503 Service Unavailable");
|
||||
}
|
||||
Assert.notNull(messageContext,"'messageContext' is required; it must not be null.");
|
||||
|
||||
try {
|
||||
this.activeCount.incrementAndGet();
|
||||
this.doInvoke(messageContext);
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -60,6 +70,9 @@ abstract public class AbstractWebServiceInboundGateway extends MessagingGatewayS
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
this.activeCount.decrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
protected void fromSoapHeaders(MessageContext messageContext, AbstractIntegrationMessageBuilder<?> builder){
|
||||
@@ -86,5 +99,17 @@ abstract public class AbstractWebServiceInboundGateway extends MessagingGatewayS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int beforeShutdown() {
|
||||
stop();
|
||||
return this.activeCount.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int afterShutdown() {
|
||||
return this.activeCount.get();
|
||||
}
|
||||
|
||||
abstract protected void doInvoke(MessageContext messageContext) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.ws;
|
||||
|
||||
import org.springframework.ws.WebServiceException;
|
||||
import org.springframework.ws.soap.server.endpoint.annotation.FaultCode;
|
||||
import org.springframework.ws.soap.server.endpoint.annotation.SoapFault;
|
||||
|
||||
/**
|
||||
* The {@link WebServiceException} extension to indicate that the server endpoint is
|
||||
* temporary unavailable.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 4.3
|
||||
*/
|
||||
@SoapFault(faultCode = FaultCode.RECEIVER)
|
||||
public class ServiceUnavailableException extends WebServiceException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ServiceUnavailableException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ServiceUnavailableException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -410,6 +410,7 @@ this list can also be simple patterns to be matched against the header names (e.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
@@ -86,6 +86,8 @@ public class SimpleWebServiceInboundGatewayTests {
|
||||
gateway.setRequestChannel(requestChannel);
|
||||
gateway.setReplyChannel(replyChannel);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.start();
|
||||
|
||||
when(context.getResponse()).thenReturn(response);
|
||||
when(response.getPayloadResult()).thenReturn(payloadResult);
|
||||
when(context.getRequest()).thenReturn(request);
|
||||
@@ -124,16 +126,20 @@ public class SimpleWebServiceInboundGatewayTests {
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("A message with payload: " + payload);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private Answer<Boolean> withReplyTo(final MessageChannel replyChannel) {
|
||||
return new Answer<Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean answer(InvocationOnMock invocation) throws Throwable {
|
||||
replyChannel.send((Message<?>) invocation.getArguments()[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,10 +21,14 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.Locale;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
@@ -34,6 +38,7 @@ import org.junit.runner.RunWith;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
@@ -58,6 +63,7 @@ import org.springframework.ws.server.endpoint.annotation.Endpoint;
|
||||
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
|
||||
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
|
||||
import org.springframework.ws.server.endpoint.mapping.UriEndpointMapping;
|
||||
import org.springframework.ws.soap.SoapBody;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.server.SoapMessageDispatcher;
|
||||
import org.springframework.ws.transport.WebServiceMessageReceiver;
|
||||
@@ -78,11 +84,15 @@ public class WebServiceInboundGatewayJavaConfigTests {
|
||||
@Autowired
|
||||
private PollableChannel webserviceRequestsQueue;
|
||||
|
||||
@Autowired
|
||||
private Lifecycle wsGateway;
|
||||
|
||||
@Test
|
||||
public void testWebServiceInboundGatewayJavaConfig() throws Exception {
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
SoapMessage request = mock(SoapMessage.class);
|
||||
SoapMessage response = mock(SoapMessage.class);
|
||||
SoapBody soapBody = mock(SoapBody.class);
|
||||
|
||||
String input = "<hello/>";
|
||||
Source payloadSource = new StringSource(input);
|
||||
@@ -91,11 +101,18 @@ public class WebServiceInboundGatewayJavaConfigTests {
|
||||
|
||||
when(context.getResponse()).thenReturn(response);
|
||||
when(response.getPayloadResult()).thenReturn(payloadResult);
|
||||
when(response.getSoapBody()).thenReturn(soapBody);
|
||||
when(context.getRequest()).thenReturn(request);
|
||||
when(request.getPayloadSource()).thenReturn(payloadSource);
|
||||
|
||||
this.messageReceiver.receive(context);
|
||||
|
||||
verify(soapBody).addServerOrReceiverFault(eq("503 Service Unavailable"), any(Locale.class));
|
||||
|
||||
this.wsGateway.start();
|
||||
|
||||
this.messageReceiver.receive(context);
|
||||
|
||||
assertTrue(output.toString().endsWith(input));
|
||||
|
||||
|
||||
@@ -138,6 +155,7 @@ public class WebServiceInboundGatewayJavaConfigTests {
|
||||
public MessageEndpoint wsGateway() {
|
||||
SimpleWebServiceInboundGateway gateway = new SimpleWebServiceInboundGateway();
|
||||
gateway.setRequestChannel(gatewayRequests());
|
||||
gateway.setAutoStartup(false);
|
||||
return gateway;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
<?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:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:ws="http://www.springframework.org/schema/integration/ws"
|
||||
xmlns:util='http://www.springframework.org/schema/util'
|
||||
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/ws
|
||||
http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd">
|
||||
|
||||
<si:message-history/>
|
||||
|
||||
<ws:inbound-gateway id="simple" request-channel="requestsVerySimple" error-channel="customErrorChannel"/>
|
||||
|
||||
<ws:inbound-gateway id="simple"
|
||||
request-channel="requestsVerySimple"
|
||||
error-channel="customErrorChannel"
|
||||
auto-startup="false"
|
||||
phase="101"/>
|
||||
|
||||
<si:channel id="customErrorChannel"/>
|
||||
|
||||
<si:channel id="requestsVerySimple"></si:channel>
|
||||
|
||||
|
||||
<si:channel id="requestsVerySimple"/>
|
||||
|
||||
<ws:inbound-gateway id="extractsPayload" request-channel="requestsSimple" extract-payload="false"/>
|
||||
|
||||
|
||||
<ws:inbound-gateway id="marshalling" request-channel="requestsMarshalling" error-channel="customErrorChannel"
|
||||
marshaller="marshaller" unmarshaller="marshaller"
|
||||
mapped-request-headers="testRequest"
|
||||
@@ -30,7 +32,7 @@
|
||||
<si:channel id="requestsMarshalling">
|
||||
<si:queue/>
|
||||
</si:channel>
|
||||
|
||||
|
||||
<si:channel id="requestsSimple">
|
||||
<si:queue/>
|
||||
</si:channel>
|
||||
|
||||
@@ -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.is;
|
||||
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.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -64,10 +65,11 @@ import org.springframework.ws.soap.SoapMessage;
|
||||
* @author Mark Fisher
|
||||
* @author Gunnar Hillert
|
||||
* @author Stephane Nicoll
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class WebServiceInboundGatewayParserTests {
|
||||
|
||||
@Autowired
|
||||
@@ -98,14 +100,10 @@ public class WebServiceInboundGatewayParserTests {
|
||||
|
||||
@Test
|
||||
public void simpleGatewayProperties() throws Exception {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(simpleGateway);
|
||||
assertThat(
|
||||
(MessageChannel) accessor.getPropertyValue("requestChannel"),
|
||||
is(requestsVerySimple));
|
||||
|
||||
assertThat(
|
||||
(MessageChannel) accessor.getPropertyValue("errorChannel"),
|
||||
is(customErrorChannel));
|
||||
assertSame(this.requestsVerySimple, TestUtils.getPropertyValue(this.simpleGateway, "requestChannel"));
|
||||
assertSame(this.customErrorChannel, TestUtils.getPropertyValue(this.simpleGateway, "errorChannel"));
|
||||
assertFalse(TestUtils.getPropertyValue(this.simpleGateway, "autoStartup", Boolean.class));
|
||||
assertEquals(101, TestUtils.getPropertyValue(this.simpleGateway, "phase"));
|
||||
}
|
||||
|
||||
//extractPayload = false
|
||||
@@ -160,7 +158,7 @@ public class WebServiceInboundGatewayParserTests {
|
||||
public void testMessageHistoryWithMarshallingGateway() throws Exception {
|
||||
MessageContext context = new DefaultMessageContext(new StubMessageFactory());
|
||||
Unmarshaller unmarshaller = mock(Unmarshaller.class);
|
||||
when(unmarshaller.unmarshal((Source)Mockito.any())).thenReturn("hello");
|
||||
when(unmarshaller.unmarshal((Source) Mockito.any())).thenReturn("hello");
|
||||
marshallingGateway.setUnmarshaller(unmarshaller);
|
||||
marshallingGateway.invoke(context);
|
||||
Message<?> message = requestsMarshalling.receive(100);
|
||||
@@ -196,7 +194,8 @@ public class WebServiceInboundGatewayParserTests {
|
||||
assertEquals(testHeaderMapper, headerMapper);
|
||||
}
|
||||
|
||||
@Autowired @Qualifier("replyTimeoutGateway")
|
||||
@Autowired
|
||||
@Qualifier("replyTimeoutGateway")
|
||||
private SimpleWebServiceInboundGateway replyTimeoutGateway;
|
||||
|
||||
@Test
|
||||
@@ -212,7 +211,7 @@ public class WebServiceInboundGatewayParserTests {
|
||||
|
||||
@Override
|
||||
public void fromHeadersToRequest(MessageHeaders headers,
|
||||
SoapMessage target) {
|
||||
SoapMessage target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user