INT-2312 Add HTTP RequestMapping support
The general idea is to use Spring-MVC as much as possible. * Introduce `RequestMapping`, `IntegrationRequestMappingHandlerMapping` * Introduce XSD nested element `<request-mapping>` for HTTP Inbound Endpoints * Introduce `inboundCommonAttributes` XSD attributeGroup for HTTP Inbound Endpoints * Introduce `IntegrationNamespaceUtils#createExpressionDefIfAttributeDefined` & `IntegrationNamespaceUtils#createDirectChannel` * Remove deprecated `name` attribute * Remove `UriPathHandlerMapping` as superseded by `IntegrationRequestMappingHandlerMapping` * Add documentation for `<request-mapping>` - Add description to Reference Manual about `<request-mapping>` * Add documentation to section 'What's new' * Add additional test for `<request-mapping>` JIRA: https://jira.springsource.org/browse/INT-2312, https://jira.springsource.org/browse/INT-2619 Additional changes: * INT-2528 Remove deprecations in HTTP module - JIRA: https://jira.springsource.org/browse/INT-2528 * Add Jackson 2 support for HTTP-inbound * Using Jackson 2 HttpMessageConverter if Jackson 2 is available in classpath * Make `RequestMapping` public * Introduce `HttpContextUtils` and move `HANDLER_MAPPING_BEAN_NAME` to it * Revert and deprecate public API * Improve JavaDocs * Improve Reference Manual Thanks also to Biju Kunjummen for his incorporated commit.
This commit is contained in:
committed by
Gunnar Hillert
parent
28131aab32
commit
6a9cb75668
@@ -7,8 +7,6 @@
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<beans:bean class="org.springframework.integration.http.inbound.UriPathHandlerMapping"/>
|
||||
|
||||
<inbound-gateway path="/test" request-channel="testChannel"
|
||||
payload-expression="T(org.springframework.web.context.request.RequestContextHolder).requestAttributes.request.queryString"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2013 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.
|
||||
@@ -32,6 +32,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.PropertyAccessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
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/http
|
||||
http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<si:message-history/>
|
||||
|
||||
@@ -18,13 +22,13 @@
|
||||
|
||||
<inbound-channel-adapter id="defaultAdapter" channel="requests" error-channel="errorChannel"/>
|
||||
|
||||
<inbound-channel-adapter id="postOnlyAdapter" channel="requests" supported-methods="POST"/>
|
||||
<inbound-channel-adapter id="postOnlyAdapter" path="/postOnly" channel="requests" supported-methods="POST"/>
|
||||
|
||||
<inbound-channel-adapter id="adapterWithCustomConverterWithDefaults" message-converters="customConverters"
|
||||
channel="requests" supported-methods="POST" merge-with-default-converters="true"/>
|
||||
channel="requests" supported-methods="DELETE" merge-with-default-converters="true"/>
|
||||
|
||||
<inbound-channel-adapter id="adapterWithCustomConverterNoDefaults" message-converters="customConverters"
|
||||
channel="requests" supported-methods="POST" />
|
||||
channel="requests" supported-methods="HEAD" />
|
||||
|
||||
<inbound-channel-adapter id="adapterNoCustomConverterNoDefaults" channel="requests" supported-methods="POST" />
|
||||
|
||||
@@ -34,43 +38,41 @@
|
||||
|
||||
<inbound-channel-adapter id="putOrDeleteAdapter" channel="requests" supported-methods="PUT, delete"/>
|
||||
|
||||
<inbound-channel-adapter id="inboundController" channel="requests" view-name="foo" error-code="oops"/>
|
||||
<inbound-channel-adapter id="inboundController" channel="requests" view-name="foo" error-code="oops">
|
||||
<request-mapping headers="BAR"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="inboundControllerViewExp" channel="requests" view-expression="'foo'"/>
|
||||
<inbound-channel-adapter id="inboundControllerViewExp" channel="requests" view-expression="'foo'">
|
||||
<request-mapping headers="BAR2"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="withMappedHeaders" channel="requests"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
mapped-request-headers="foo,bar">
|
||||
<request-mapping headers="foo=bar"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="inboundAdapterWithExpressions"
|
||||
path="/fname/{f}/lname/{l}"
|
||||
channel="requests"
|
||||
path="/fname/{f}/lname/{l}"
|
||||
channel="requests"
|
||||
mapped-request-headers="foo,bar"
|
||||
payload-expression="#pathVariables.f">
|
||||
<header name="lname" expression="#pathVariables.l"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter name="/fname/{blah}/lname/{boo}"
|
||||
path="/fname/{f}/lname/{l}"
|
||||
channel="requests"
|
||||
mapped-request-headers="foo,bar"
|
||||
payload-expression="#pathVariables.f">
|
||||
<header name="lname" expression="#pathVariables.l"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter name="/fname/{f}/lname/{l}"
|
||||
channel="requests"
|
||||
<inbound-channel-adapter channel="requests"
|
||||
mapped-request-headers="foo,bar"
|
||||
payload-expression="#pathVariables.f">
|
||||
<request-mapping headers="invalid"/>
|
||||
<header name="lname" expression="#pathVariables.l"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="autoChannel"
|
||||
path="/fname/{f}/lname/{l}"
|
||||
path="/fname/{f}/lname2/{l}"
|
||||
mapped-request-headers="foo,bar"
|
||||
payload-expression="#pathVariables.f">
|
||||
<header name="lname" expression="#pathVariables.l"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<si:bridge input-channel="autoChannel" output-channel="nullChannel" />
|
||||
<si:bridge input-channel="autoChannel" output-channel="nullChannel"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -20,9 +20,9 @@ import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
@@ -58,7 +58,11 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -66,7 +70,6 @@ import org.springframework.util.MultiValueMap;
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -76,6 +79,9 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private PollableChannel requests;
|
||||
|
||||
@Autowired
|
||||
private HandlerMapping integrationRequestMappingHandlerMapping;
|
||||
|
||||
@Autowired
|
||||
private HttpRequestHandlingMessagingGateway defaultAdapter;
|
||||
|
||||
@@ -95,14 +101,6 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private HttpRequestHandlingMessagingGateway inboundAdapterWithExpressions;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("/fname/{blah}/lname/{boo}")
|
||||
private HttpRequestHandlingMessagingGateway inboundAdapterWithNameAndExpressions;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("/fname/{f}/lname/{l}")
|
||||
private HttpRequestHandlingMessagingGateway inboundAdapterWithNameNoPath;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("adapterWithCustomConverterNoDefaults")
|
||||
private HttpRequestHandlingMessagingGateway adapterWithCustomConverterNoDefaults;
|
||||
@@ -167,7 +165,15 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
String requestURI = "/fname/bill/lname/clinton";
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables("/fname/{f}/lname/{l}", requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
inboundAdapterWithExpressions.handleRequest(request, response);
|
||||
@@ -180,60 +186,20 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
assertEquals("clinton", message.getHeaders().get("lname"));
|
||||
}
|
||||
|
||||
@Test // ensure that 'path' takes priority over name
|
||||
// INT-1677
|
||||
public void withNameAndExpressionsAndPath() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
inboundAdapterWithNameAndExpressions.handleRequest(request, response);
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
Message<?> message = requests.receive(0);
|
||||
assertNotNull(message);
|
||||
Object payload = message.getPayload();
|
||||
assertTrue(payload instanceof String);
|
||||
assertEquals("bill", payload);
|
||||
assertEquals("clinton", message.getHeaders().get("lname"));
|
||||
}
|
||||
|
||||
@Test(expected=SpelEvaluationException.class)
|
||||
// INT-1677
|
||||
public void withNameAndExpressionsNoPath() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
inboundAdapterWithNameNoPath.handleRequest(request, response);
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
Message<?> message = requests.receive(0);
|
||||
assertNotNull(message);
|
||||
Object payload = message.getPayload();
|
||||
assertTrue(payload instanceof String);
|
||||
assertEquals("hello", payload); // default payload
|
||||
assertNull(message.getHeaders().get("lname"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void getRequestNotAllowed() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setParameter("foo", "bar");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
postOnlyAdapter.handleRequest(request, response);
|
||||
assertEquals(HttpServletResponse.SC_METHOD_NOT_ALLOWED, response.getStatus());
|
||||
Message<?> message = requests.receive(0);
|
||||
assertNull(message);
|
||||
request.setRequestURI("/postOnly");
|
||||
try {
|
||||
this.integrationRequestMappingHandlerMapping.getHandler(request);
|
||||
}
|
||||
catch (HttpRequestMethodNotSupportedException e) {
|
||||
assertEquals("GET", e.getMethod());
|
||||
assertArrayEquals(new String[] {"POST"}, e.getSupportedMethods());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -241,10 +207,7 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContent("test".getBytes());
|
||||
|
||||
//request.setContentType("text/plain"); //Works in Spring 3.1.2.RELEASE but not in Spring 3.0.7.RELEASE
|
||||
//Instead use:
|
||||
request.addHeader("Content-Type", "text/plain");
|
||||
request.setContentType("text/plain");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
postOnlyAdapter.handleRequest(request, response);
|
||||
@@ -267,10 +230,7 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
new ObjectOutputStream(byteStream).writeObject(obj);
|
||||
request.setContent(byteStream.toByteArray());
|
||||
|
||||
// //request.setContentType("application/x-java-serialized-object"); //Works in Spring 3.1.2.RELEASE but not in Spring 3.0.7.RELEASE
|
||||
// //Instead use:
|
||||
request.addHeader("Content-Type", "application/x-java-serialized-object");
|
||||
request.setContentType("application/x-java-serialized-object");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
@@ -284,13 +244,11 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putOrDeleteMethodsSupported() throws Exception {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(putOrDeleteAdapter);
|
||||
List<String> supportedMethods = (List<String>) accessor.getPropertyValue("supportedMethods");
|
||||
assertEquals(2, supportedMethods.size());
|
||||
assertTrue(supportedMethods.contains(HttpMethod.PUT));
|
||||
assertTrue(supportedMethods.contains(HttpMethod.DELETE));
|
||||
HttpMethod[] supportedMethods =
|
||||
TestUtils.getPropertyValue(putOrDeleteAdapter, "requestMapping.methods", HttpMethod[].class);
|
||||
assertEquals(2, supportedMethods.length);
|
||||
assertArrayEquals(new HttpMethod[]{HttpMethod.PUT, HttpMethod.DELETE}, supportedMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
@@ -19,27 +18,35 @@
|
||||
</si:channel>
|
||||
|
||||
<inbound-gateway id="inboundGateway"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
convert-exceptions="true"
|
||||
request-timeout="1234"
|
||||
reply-timeout="4567"
|
||||
error-channel="errorChannel"/>
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
convert-exceptions="true"
|
||||
request-timeout="1234"
|
||||
reply-timeout="4567"
|
||||
error-channel="errorChannel"/>
|
||||
|
||||
<inbound-gateway id="inboundController" request-channel="requests" reply-channel="responses" view-name="foo"
|
||||
error-code="oops">
|
||||
<request-mapping headers="BAR"/>
|
||||
</inbound-gateway>
|
||||
|
||||
<inbound-gateway id="inboundGatewayWithOneCustomConverter"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
supported-methods="DELETE"
|
||||
message-converters="customConverters"/>
|
||||
|
||||
<inbound-gateway id="inboundGatewayNoDefaultConverters"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
supported-methods="TRACE"
|
||||
message-converters="customConverters"
|
||||
merge-with-default-converters="false"/>
|
||||
|
||||
<inbound-gateway id="inboundGatewayWithCustomAndDefaultConverters"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
supported-methods="HEAD"
|
||||
message-converters="customConverters"
|
||||
merge-with-default-converters="true"/>
|
||||
|
||||
@@ -47,26 +54,28 @@
|
||||
<beans:bean class="org.springframework.integration.http.converter.SerializingHttpMessageConverter"/>
|
||||
</util:list>
|
||||
|
||||
|
||||
<inbound-gateway id="inboundController" request-channel="requests" reply-channel="responses" view-name="foo" error-code="oops"/>
|
||||
|
||||
<inbound-gateway id="inboundControllerViewExp"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
view-expression="'bar'"
|
||||
error-code="oops"/>
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
view-expression="'bar'"
|
||||
error-code="oops">
|
||||
<request-mapping headers="BAR2"/>
|
||||
</inbound-gateway>
|
||||
|
||||
<inbound-gateway id="withMappedHeaders" request-channel="requests"
|
||||
mapped-response-headers="abc, xyz"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
|
||||
mapped-response-headers="abc, xyz"
|
||||
mapped-request-headers="foo,bar">
|
||||
<request-mapping headers="foo=bar"/>
|
||||
</inbound-gateway>
|
||||
<inbound-gateway id="withMappedHeadersAndConverter" request-channel="requests"
|
||||
mapped-response-headers="abc, xyz, person"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
mapped-response-headers="abc, xyz, person"
|
||||
mapped-request-headers="foo,bar">
|
||||
<request-mapping headers="foo=bar2"/>
|
||||
</inbound-gateway>
|
||||
|
||||
<si:converter ref="personConverter"/>
|
||||
|
||||
<beans:bean id="personConverter" class="org.springframework.integration.http.config.HttpInboundGatewayParserTests.PersonConverter"/>
|
||||
|
||||
<beans:bean id="personConverter"
|
||||
class="org.springframework.integration.http.config.HttpInboundGatewayParserTests$PersonConverter"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -68,6 +68,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
* @author Biju Kunjummen
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@@ -119,8 +120,8 @@ public class HttpInboundGatewayParserTests {
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "errorChannel"));
|
||||
MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(
|
||||
gateway, "messagingTemplate", MessagingTemplate.class);
|
||||
assertEquals(Long.valueOf(1234), TestUtils.getPropertyValue(messagingTemplate, "sendTimeout"));
|
||||
assertEquals(Long.valueOf(4567), TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout"));
|
||||
assertEquals(1234L, TestUtils.getPropertyValue(messagingTemplate, "sendTimeout"));
|
||||
assertEquals(4567L, TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout"));
|
||||
|
||||
boolean registerDefaultConverters = TestUtils.getPropertyValue(gateway,"mergeWithDefaultConverters", Boolean.class);
|
||||
assertFalse("By default the register-default-converters flag should be false", registerDefaultConverters);
|
||||
@@ -148,9 +149,7 @@ public class HttpInboundGatewayParserTests {
|
||||
gateway.handleRequest(request, response);
|
||||
assertThat(response.getStatus(), is(HttpServletResponse.SC_OK));
|
||||
|
||||
//MockHttpServletResponse#getContentType() works in Spring 3.1.2.RELEASE but not in 3.0.7.RELEASE
|
||||
//For 3.0.7.RELEASE we have to rely on MockHttpServletResponse#getHeader instead
|
||||
assertEquals(response.getHeader("Content-Type"), "application/x-java-serialized-object");
|
||||
assertEquals(response.getContentType(), "application/x-java-serialized-object");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -34,12 +34,15 @@ import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
@@ -69,10 +72,14 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
RequestMapping requestMapping = new RequestMapping();
|
||||
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestMapping(requestMapping);
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Object result = gateway.doHandleRequest(request, response);
|
||||
@@ -97,12 +104,24 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
String requestURI = "/fname/bill/lname/clinton";
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables("/fname/{f}/lname/{l}", requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
RequestMapping requestMapping = new RequestMapping();
|
||||
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestMapping(requestMapping);
|
||||
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables.f"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
@@ -130,12 +149,24 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
String requestURI = "/fname/bill/lname/clinton";
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables("/fname/{f}/lname/{l}", requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
RequestMapping requestMapping = new RequestMapping();
|
||||
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestMapping(requestMapping);
|
||||
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns:int-http="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/http
|
||||
http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
|
||||
|
||||
<int-http:inbound-gateway path="/path1,/path2"
|
||||
request-channel="multiplePathsChannel"/>
|
||||
|
||||
<int:transformer input-channel="multiplePathsChannel"
|
||||
expression="T(org.springframework.integration.http.inbound.Int2312RequestMappingIntegrationTests).TEST_STRING_MULTIPLE_PATHS"/>
|
||||
|
||||
<util:constant id="TEST_PATH"
|
||||
static-field="org.springframework.integration.http.inbound.Int2312RequestMappingIntegrationTests.TEST_PATH"/>
|
||||
|
||||
<int-http:inbound-gateway path="#{TEST_PATH}"
|
||||
request-channel="toLowerCaseChannel"
|
||||
payload-expression="#pathVariables.value">
|
||||
<int-http:request-mapping headers="toLowerCase"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="toLowerCaseChannel" expression="payload.toLowerCase()"/>
|
||||
|
||||
<int-http:inbound-gateway path="#{TEST_PATH}"
|
||||
request-channel="toUpperCaseChannel"
|
||||
payload-expression="#pathVariables.value">
|
||||
<int-http:request-mapping headers="toUpperCase"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="toUpperCaseChannel" expression="payload.toUpperCase()"/>
|
||||
|
||||
<int-http:inbound-gateway path="/params"
|
||||
request-channel="twoParamsChannel">
|
||||
<int-http:request-mapping params="param1,param2"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="twoParamsChannel" expression="'User=1;account=1'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/params"
|
||||
request-channel="onlyOneParamChannel">
|
||||
<int-http:request-mapping params="param1,!param2"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="onlyOneParamChannel" expression="'User=1'"/>
|
||||
|
||||
|
||||
<int-http:inbound-gateway path="/consumes"
|
||||
request-channel="consumesNonXmlChannel"
|
||||
supported-methods="GET,PUT">
|
||||
<int-http:request-mapping consumes="!text/xml,text/*"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="consumesNonXmlChannel" expression="'BAR'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/consumes"
|
||||
request-channel="consumesXmlChannel"
|
||||
supported-methods="GET,PUT">
|
||||
<int-http:request-mapping consumes="text/xml"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="consumesXmlChannel" expression="'<test>TEXT_XML</test>'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/produces"
|
||||
request-channel="contentXmlChannel">
|
||||
<int-http:request-mapping produces="application/xml"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="contentXmlChannel" expression="'<test>XML</test>'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/produces"
|
||||
request-channel="contentNonXmlChannel">
|
||||
<int-http:request-mapping produces="!application/xml"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="contentNonXmlChannel" expression="'{"json":"body"}'"/>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2013 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.inbound;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
//INT-2312
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class Int2312RequestMappingIntegrationTests {
|
||||
|
||||
public static final String TEST_PATH = "/test/{value}";
|
||||
|
||||
public static final String TEST_STRING_MULTIPLE_PATHS = "Multiple Paths The Same Endpoint";
|
||||
|
||||
@Autowired
|
||||
private HandlerMapping handlerMapping;
|
||||
|
||||
private HandlerAdapter handlerAdapter = new HttpRequestHandlerAdapter();
|
||||
|
||||
@Test
|
||||
public void testMultiplePathsTheSameEndpoint() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setRequestURI("/path1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
assertEquals(TEST_STRING_MULTIPLE_PATHS, response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setRequestURI("/path2");
|
||||
response = new MockHttpServletResponse();
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
assertEquals(TEST_STRING_MULTIPLE_PATHS, response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testURIVariablesAndHeaders() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
String testRequest = "aBc";
|
||||
String requestURI = "/test/" + testRequest;
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables(TEST_PATH, requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.addHeader("toLowerCase", true);
|
||||
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
final String testResponse = response.getContentAsString();
|
||||
assertEquals(testRequest.toLowerCase(), testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParams() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/params");
|
||||
Object handler = null;
|
||||
try {
|
||||
handler = this.handlerMapping.getHandler(request);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// There is no matching handlers and some default handler
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleNoMatch
|
||||
assertTrue(e instanceof UnsatisfiedServletRequestParameterException);
|
||||
}
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/params");
|
||||
request.addParameter("param1", "1");
|
||||
request.addParameter("param2", "1");
|
||||
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
String testResponse = response.getContentAsString();
|
||||
assertEquals("User=1;account=1", testResponse);
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/params");
|
||||
request.addParameter("param1", "1");
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
testResponse = response.getContentAsString();
|
||||
assertEquals("User=1", testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumes() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/consumes");
|
||||
request.setContentType("text/plain");
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
String testResponse = response.getContentAsString();
|
||||
assertEquals("BAR", testResponse);
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/consumes");
|
||||
request.setContentType("text/xml");
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
testResponse = response.getContentAsString();
|
||||
assertEquals("<test>TEXT_XML</test>", testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProduces() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/produces");
|
||||
request.addHeader("Accept", "application/xml");
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
assertEquals(Collections.singleton(MediaType.APPLICATION_XML),
|
||||
request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE));
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
String testResponse = response.getContentAsString();
|
||||
assertEquals("<test>XML</test>", testResponse);
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/produces");
|
||||
request.addHeader("Accept", "application/json");
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
assertNull("Negated expression should not be listed as a producible type",
|
||||
request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE));
|
||||
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
testResponse = response.getContentAsString();
|
||||
assertEquals("{\"json\":\"body\"}", testResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -501,11 +502,10 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests {
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void validateCustomHeadersWithNonStringValuesAndDefaultConverterOnly() throws Exception{
|
||||
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
|
||||
mapper.setOutboundHeaderNames(new String[] {"customHeader*"});
|
||||
ConversionService cs = ConversionServiceFactory.createDefaultConversionService();
|
||||
ConversionService cs = new DefaultConversionService();
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("integrationConversionService", cs);
|
||||
mapper.setBeanFactory(beanFactory);
|
||||
@@ -523,11 +523,10 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void validateCustomHeadersWithNonStringValuesAndDefaultConverterWithCustomConverter() throws Exception{
|
||||
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
|
||||
mapper.setOutboundHeaderNames(new String[] {"customHeader*"});
|
||||
GenericConversionService cs = ConversionServiceFactory.createDefaultConversionService();
|
||||
GenericConversionService cs = new DefaultConversionService();
|
||||
cs.addConverter(new TestClassConverter());
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("integrationConversionService", cs);
|
||||
|
||||
Reference in New Issue
Block a user