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

@@ -75,7 +75,7 @@
"multipartResolver" (the same name expected by Spring's DispatcherServlet). If it does in fact locate that
bean, then the support for MultipartFiles will be enabled on the inbound request mapper. Otherwise, it will
fail when trying to map a multipart-file request to a Spring Integration Message. For more on Spring's
support for MultipartResolvers, refer to the <ulink url="http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html#mvc-multipart">Spring Reference Manual</ulink>.
support for MultipartResolvers, refer to the <ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-multipart">Spring Reference Manual</ulink>.
</note>
</para>
<para>
@@ -139,11 +139,10 @@ By default the HTTP request will be generated using an instance of <classname>Si
<classname>HttpURLConnection</classname>. Use of the Apache Commons HTTP Client is also supported through the provided
<classname>CommonsClientHttpRequestFactory</classname> which can be injected as shown above.
</para>
<para>
<note>
In the case of the Outbound Gateway, the reply message produced by the gateway will contain all Message Headers present in the request message.
</note>
</para>
<note>
In the case of the Outbound Gateway, the reply message produced by the gateway
will contain all Message Headers present in the request message.
</note>
<para><emphasis>Cookies</emphasis></para>
<para>
Basic cookie support is provided by the <emphasis>transfer-cookies</emphasis> attribute on the outbound gateway. When
@@ -158,8 +157,7 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
If <emphasis>transfer-cookies</emphasis> is false, any <emphasis>Set-Cookie</emphasis> header received will
remain as <emphasis>Set-Cookie</emphasis> in the reply message, and will be dropped on subsequent sends.
</para>
<para>
<note>
<note>
<title>Note: Empty Repsonse Bodies</title>
HTTP is a request/response protocol. However the response may not have a body, just headers.
In this case, the <classname>HttpRequestExecutingMessageHandler</classname> produces
@@ -174,8 +172,7 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
routing logic after the Http Outbound Gateway. You could also use a
<code>&lt;payload-type-router/&gt;</code> to route messages with an <classname>HttpEntity</classname>
to a different flow than that used for responses with a body.
</note>
</para>
</note>
</section>
<section id="http-namespace">
@@ -224,88 +221,140 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
request-channel="requests"
reply-channel="responses"/>]]></programlisting>
<important>
<para>
Beginning with <emphasis>Spring Integration 2.1</emphasis> the
<emphasis>HTTP Inbound Gateway</emphasis> and the <emphasis>HTTP
Inbound Channel Adapter</emphasis> should use the <emphasis>path</emphasis>
attribute instead of the <emphasis>name</emphasis> attribute for
specifying the request path. The <emphasis>name</emphasis> attribute
for those 2 components has been deprecated.
</para>
<para>
If you simply want to identify component itself within your application
context, please use the <emphasis>id</emphasis> attribute.
</para>
</important>
<para><emphasis>Request Mapping support</emphasis></para>
<note>
<emphasis>Spring Integration 3.0</emphasis> is improving the REST support by introducing the
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html"
>IntegrationRequestMappingHandlerMapping</ulink></interfacename>. The implementation relies on the enhanced REST support provided by Spring Framework 3.1 or higher.
</note>
<para>
The parsing of the <emphasis>HTTP Inbound Gateway</emphasis> or the
<emphasis>HTTP Inbound Channel Adapter</emphasis> registers an <code>integrationRequestMappingHandlerMapping</code>
bean of type
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html"
>IntegrationRequestMappingHandlerMapping</ulink></interfacename>, in case there is none registered, yet. This particular implementation of the
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html"
><interfacename>HandlerMapping</interfacename></ulink> delegates its logic to the
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.html"
><interfacename>RequestMappingInfoHandlerMapping</interfacename></ulink>. The implementation provides similar functionality as the one provided by the
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html"
><classname>org.springframework.web.bind.annotation.RequestMapping</classname></ulink> annotation in Spring MVC.
</para>
<note>
For more information, please see
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping">Mapping Requests With @RequestMapping</ulink>.
</note>
<para>
For this purpose, <emphasis>Spring Integration 3.0</emphasis> introduces the <code>&lt;request-mapping&gt;</code> sub-element.
This optional sub-element can be added to the <code>&lt;http:inbound-channel-adapter&gt;</code> and the <code>&lt;http:inbound-gateway&gt;</code>.
It works in conjunction with the <code>path</code> and <code>supported-methods</code> attributes:
</para>
<programlisting language="xml"><![CDATA[<inbound-gateway id="inboundController"
request-channel="requests"
reply-channel="responses"
path="/foo/{fooId}"
supported-methods="GET"
view-name="foo"
error-code="oops">
<request-mapping headers="User-Agent"
params="myParam=myValue"
consumes="application/json"
produces="!text/plain"/>
</inbound-gateway>]]></programlisting>
<para>
Based on this configuration, the namespace parser creates an instance of the <classname>IntegrationRequestMappingHandlerMapping</classname> (if none exists, yet),
a <classname>HttpRequestHandlingController</classname> bean and associated with it an instance of
<ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/RequestMapping.html"
><classname>RequestMapping</classname></ulink>, which in turn, is converted to the Spring MVC
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfo.html"
><classname>RequestMappingInfo</classname></ulink>.
</para>
<para>
The <code>&lt;request-mapping&gt;</code> sub-element provides the following attributes:
</para>
<itemizedlist>
<listitem>headers</listitem>
<listitem>params</listitem>
<listitem>consumes</listitem>
<listitem>produces</listitem>
</itemizedlist>
<para>
With the <code>path</code> and <code>supported-methods</code> attributes of the <code>&lt;http:inbound-channel-adapter&gt;</code> or
the <code>&lt;http:inbound-gateway&gt;</code>, <code>&lt;request-mapping&gt;</code> attributes translate directly into the respective options
provided by the <classname>org.springframework.web.bind.annotation.RequestMapping</classname> annotation in Spring MVC.
</para>
<para>
The <code>&lt;request-mapping&gt;</code> sub-element allows you to configure
several <emphasis>Spring Integration</emphasis> HTTP Inbound Endpoints to the
same <code>path</code> (or even the same <code>supported-methods</code>)
and to provide different downstream message flows based on incoming HTTP requests.
</para>
<para>
Alternatively, you can also declare just one HTTP Inbound Endpoint and
apply routing and filtering logic within the <emphasis>Spring Integration</emphasis>
flow to achieve the same result. This allows you to get the <interfacename>Message</interfacename>
into the flow as early as possibly, e.g.:
</para>
<programlisting language="xml"><![CDATA[<int-http:inbound-gateway request-channel="httpMethodRouter"
supported-methods="GET,DELETE"
path="/process/{entId}"
payload-expression="#pathVariables.entId"/>
<para><emphasis>Defining the UriPathHandlerMapping</emphasis></para>
<int:router input-channel="httpMethodRouter" expression="headers.http_requestMethod">
<int:mapping value="GET" channel="in1"/>
<int:mapping value="DELETE" channel="in2"/>
</int:router>
<para>
In order to use the <emphasis>HTTP Inbound Gateway</emphasis> or the
<emphasis>HTTP Inbound Channel Adapter</emphasis> you must define a
<int:service-activator input-channel="in1" ref="service" method="getEntity"/>
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/UriPathHandlerMapping.html"
>UriPathHandlerMapping</ulink></interfacename>. This particular implementation of the
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html"
><interfacename>HandlerMapping</interfacename></ulink> matches against
the value of the <emphasis>path</emphasis> attribute.
</para>
<int:service-activator input-channel="in2" ref="service" method="delete"/>]]></programlisting>
<para>
For more information regarding <emphasis>Handler Mappings</emphasis>, please see:
</para>
<itemizedlist>
<listitem>
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping"></ulink>
</listitem>
</itemizedlist>
<programlisting language="xml"><![CDATA[<bean class="org.springframework.integration.http.inbound.UriPathHandlerMapping"/>]]></programlisting>
<para>
For more information regarding <emphasis>Handler Mappings</emphasis>, please
see:
</para>
<para><emphasis>URI Template Variables and Expressions</emphasis></para>
<para>
By Using the <emphasis>path</emphasis> attribute in conjunction with the
<emphasis>payload-expression</emphasis> attribute as well as the <emphasis>
header</emphasis> sub-element, you have a high degree of flexibility for
mapping inbound request data.
</para>
<para>
In the following example configuration, an Inbound Channel Adapter is
configured to accept requests using the following URI:
<emphasis>/first-name/{firstName}/last-name/{lastName}</emphasis>
</para>
<para>
Using the <emphasis>payload-expression</emphasis> attribute, the URI
template variable <emphasis>{firstName}</emphasis> is mapped to be the
Message payload, while the <emphasis>{lastName}</emphasis> URI template
variable will map to the <emphasis>lname</emphasis> Message header.
</para>
<itemizedlist>
<listitem>
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping"></ulink>
</listitem>
</itemizedlist>
<para><emphasis>URI Template Variables and Expressions</emphasis></para>
<para>
By Using the <emphasis>path</emphasis> attribute in conjunction with the
<emphasis>payload-expression</emphasis> attribute as well as the <emphasis>
header</emphasis> sub-element, you have a high degree of flexiblity for
mapping inbound request data.
</para>
<para>
In the following example configuration, an Inbound Channel Adapter is
configured to accept requests using the following URI:
<emphasis>/first-name/{firstName}/last-name/{lastName}</emphasis>
</para>
<para>
Using the <emphasis>payload-expression</emphasis> attribute, the URI
template variable <emphasis>{firstName}</emphasis> is mapped to be the
Message payload, while the <emphasis>{lastName}</emphasis> URI template
variable will map to the <emphasis>lname</emphasis> Message header.
</para>
<programlisting language="xml"><![CDATA[<int-http:inbound-channel-adapter id="inboundAdapterWithExpressions"
<programlisting language="xml"><![CDATA[<int-http:inbound-channel-adapter id="inboundAdapterWithExpressions"
path="/first-name/{firstName}/last-name/{lastName}"
channel="requests"
payload-expression="#pathVariables.firstName">
<int-http:header name="lname" expression="#pathVariables.lastName"/>
</int-http:inbound-channel-adapter>]]></programlisting>
<para>
For more information about <emphasis>URI template variables</emphasis>,
please see the Spring Reference Manual:
</para>
<para>
For more information about <emphasis>URI template variables</emphasis>,
please see the Spring Reference Manual:
</para>
<itemizedlist>
<listitem>
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/spring-framework-reference.html#mvc-ann-requestmapping"></ulink>
</listitem>
</itemizedlist>
<para><emphasis>Outbound</emphasis></para>
<itemizedlist>
<listitem>
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates"></ulink>
</listitem>
</itemizedlist>
<para><emphasis>Outbound</emphasis></para>
<para>
To configure the outbound gateway you can use the namespace support as well. The following code snippet shows the different configuration options for an outbound Http gateway. Most importantly, notice that the 'http-method' and 'expected-response-type' are provided. Those are two of the most commonly configured values. The
default http-method is POST, and the default response type is <emphasis>null</emphasis>. With a null response type, the payload of the reply Message would

View File

@@ -119,6 +119,19 @@
For more information see <xref linkend="spel-property-accessors" />.
</para>
</section>
<section id="3.0-request-mapping">
<title>HTTP Request Mapping</title>
<para>
The HTTP module now provides powerful Request Mapping support for Inbound Endpoints. Class <classname>UriPathHandlerMapping</classname>
was replaced by <classname>IntegrationRequestMappingHandlerMapping</classname>, which is registered under the bean name
<code>integrationRequestMappingHandlerMapping</code> in the application context. Upon parsing of the HTTP Inbound Endpoint,
a new <classname>IntegrationRequestMappingHandlerMapping</classname> bean is either registered or an existing bean is being reused.
To achieve flexible Request Mapping configuration, Spring Integration provides the <code>&lt;request-mapping/&gt;</code>
sub-element for <code>&lt;http:inbound-channel-adapter/&gt;</code> and <code>&lt;http:inbound-gateway/&gt;</code>.
Both HTTP Inbound Endpoints are now fully based on the Request Mapping infrastructure that was introduced with Spring MVC 3.1.
For more information see <xref linkend="http-namespace"/>.
</para>
</section>
</section>
<section id="3.0-general">
@@ -260,14 +273,14 @@
<listitem>
<emphasis role="bold">Outbound Endpoint 'encode-uri'</emphasis> - <code>&lt;http:outbound-gateway/&gt;</code>
and <code>&lt;http:outbound-channel-adapter/&gt;</code> now
provides an <code>encode-uri</code> attribute to allow disabling the encoding of the URI object
provide an <code>encode-uri</code> attribute to allow disabling the encoding of the URI object
before sending the request.
</listitem>
<listitem>
<emphasis role="bold">Inbound Endpoint 'merge-with-default-converters'</emphasis> -
<code>&lt;http:inbound-gateway/&gt;</code> and <code>&lt;http:inbound-channel-adapter/&gt;</code> now
have a <code>merge-with-default-converters</code> attribute to include the list of default
<interfacename>HttpMessageConverter</interfacename> after the custom message converters.
<interfacename>HttpMessageConverter</interfacename>s after the custom message converters.
</listitem>
<listitem>
<emphasis role="bold">'If-(Un)Modified-Since' HTTP headers</emphasis> - previously,