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:
Artem Bilan
2012-08-21 18:04:45 +03:00
committed by Gunnar Hillert
parent 28131aab32
commit 6a9cb75668
26 changed files with 1428 additions and 761 deletions

View File

@@ -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"/>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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();

View File

@@ -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="'&lt;test&gt;TEXT_XML&lt;/test&gt;'"/>
<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="'&lt;test&gt;XML&lt;/test&gt;'"/>
<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="'{&quot;json&quot;:&quot;body&quot;}'"/>
</beans:beans>

View File

@@ -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);
}
}

View File

@@ -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);