Files
spring-integration/src/reference/docbook/http.xml
Gunnar Hillert 06831b9e22 INT-2882 Upgrade DocBook Reference Plugin to 0.2.6
For reference see: https://jira.springsource.org/browse/INT-2882

* Verify spacing
* Ensure all source code samples are typed: e.g. <programlisting language="xml">
* Ensure source code fits space in PDF format
2013-03-12 18:45:25 -04:00

771 lines
39 KiB
XML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="http"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>HTTP Support</title>
<section id="http-intro">
<title>Introduction</title>
<para>
The HTTP support allows for the execution of HTTP requests and the processing of inbound HTTP requests. Because interaction over HTTP is always synchronous, even if all that is returned is a 200 status code, the HTTP support consists of two gateway implementations:
<classname>HttpInboundEndpoint</classname> and <classname>HttpRequestExecutingMessageHandler</classname>.
</para>
</section>
<section id="http-inbound">
<title>Http Inbound Gateway</title>
<para>
To receive messages over HTTP, you need to use an <emphasis>HTTP Inbound
Channel Adapter</emphasis> or <emphasis>Gateway</emphasis>. To support
the <emphasis>HTTP Inbound Adapters</emphasis>, they need to be deployed
within a servlet container such as <ulink url="http://tomcat.apache.org/">Apache Tomcat</ulink>
or <ulink url="http://www.eclipse.org/jetty/">Jetty</ulink>. The easiest
way to do this is to use Spring's
<classname><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/context/support/HttpRequestHandlerServlet.html">HttpRequestHandlerServlet</ulink></classname>,
by providing the following servlet definition in the <emphasis>web.xml</emphasis> file:
</para>
<programlisting language="xml"><![CDATA[<servlet>
<servlet-name>inboundGateway</servlet-name>
<servlet-class>o.s.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>]]></programlisting>
<para>
Notice that the servlet name matches the bean name. For more information
on using the <classname>HttpRequestHandlerServlet</classname>, see chapter
"<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/remoting.html">Remoting and web services using Spring</ulink>",
which is part of the Spring Framework Reference documentation.
</para>
<para>
If you are running within a Spring MVC application, then the aforementioned
explicit servlet definition is not necessary. In that case, the bean name
for your gateway can be matched against the URL path just like a Spring
MVC Controller bean. For more information, please see the chapter
"<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html">Web MVC framework</ulink>",
which is part of the Spring Framework Reference documentation.
</para>
<tip>
For a sample application and the corresponding configuration, please see the
<ulink url="https://github.com/SpringSource/spring-integration-samples">Spring Integration Samples</ulink>
repository. It contains the
<ulink url="https://github.com/SpringSource/spring-integration-samples/tree/master/basic/http">Http Sample</ulink>
application demonstrating Spring Integration's HTTP support.
</tip>
<para>
Below is an example bean definition for a simple HTTP inbound endpoint.
</para>
<programlisting language="xml"><![CDATA[<bean id="httpInbound"
class="org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway">
<property name="requestChannel" ref="httpRequestChannel" />
<property name="replyChannel" ref="httpReplyChannel" />
</bean>]]></programlisting>
<para>
The <classname>HttpRequestHandlingMessagingGateway</classname> accepts a list of <interfacename>HttpMessageConverter</interfacename> instances or else
relies on a default list. The converters allow
customization of the mapping from <interfacename>HttpServletRequest</interfacename> to <interfacename>Message</interfacename>. The default converters
encapsulate simple strategies, which for
example will create a String message for a <emphasis>POST</emphasis> request where the content type starts with "text", see the Javadoc for
full details.
</para>
<para>Starting with this release MultiPart File support was implemented. If the request has been wrapped as a
<emphasis>MultipartHttpServletRequest</emphasis>, when using the default converters, that request will be converted
to a Message payload that is a MultiValueMap containing values that may be byte arrays, Strings, or instances of
Spring's <interfacename>MultipartFile</interfacename> depending on the content type of the individual parts.
<note>
The HTTP inbound Endpoint will locate a MultipartResolver in the context if one exists with the bean name
"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>.
</note>
</para>
<para>
In sending a response to the client there are a number of ways to customize the behavior of the gateway. By default the gateway will
simply acknowledge that the request was received by sending a 200 status code back. It is possible to customize this response by providing a
'viewName' to be resolved by the Spring MVC <interfacename>ViewResolver</interfacename>.
In the case that the gateway should expect a reply to the <interfacename>Message</interfacename> then setting the <property>expectReply</property> flag
(constructor argument) will cause
the gateway to wait for a reply <interfacename>Message</interfacename> before creating an HTTP response. Below is an example of a gateway
configured to serve as a Spring MVC Controller with a view name. Because of the constructor arg value of TRUE, it wait for a reply. This also shows
how to customize the HTTP methods accepted by the gateway, which
are <emphasis>POST</emphasis> and <emphasis>GET</emphasis> by default.
<programlisting language="xml"><![CDATA[<bean id="httpInbound"
class="org.springframework.integration.http.inbound.HttpRequestHandlingController">
<constructor-arg value="true" /> <!-- indicates that a reply is expected -->
<property name="requestChannel" ref="httpRequestChannel" />
<property name="replyChannel" ref="httpReplyChannel" />
<property name="viewName" value="jsonView" />
<property name="supportedMethodNames" >
<list>
<value>GET</value>
<value>DELETE</value>
</list>
</property>
</bean>]]></programlisting>
The reply message will be available in the Model map. The key that is used
for that map entry by default is 'reply', but this can be overridden by setting the
'replyKey' property on the endpoint's configuration.
</para>
</section>
<section id="http-outbound">
<title>Http Outbound Gateway</title>
<para>
To configure the <classname>HttpRequestExecutingMessageHandler</classname> write a bean definition like this:
</para>
<programlisting language="xml"><![CDATA[<bean id="httpOutbound"
class="org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler">
<constructor-arg value="http://localhost:8080/example" />
<property name="outputChannel" ref="responseChannel" />
</bean>]]></programlisting>
<para>
This bean definition will execute HTTP requests by delegating to a <classname>RestTemplate</classname>. That template in turn delegates
to a list of HttpMessageConverters to generate the HTTP request body from the Message payload. You can configure those converters as well
as the ClientHttpRequestFactory instance to use:
</para>
<programlisting language="xml"><![CDATA[<bean id="httpOutbound"
class="org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler">
<constructor-arg value="http://localhost:8080/example" />
<property name="outputChannel" ref="responseChannel" />
<property name="messageConverters" ref="messageConverterList" />
<property name="requestFactory" ref="customRequestFactory" />
</bean>]]></programlisting>
<para>
By default the HTTP request will be generated using an instance of <classname>SimpleClientHttpRequestFactory</classname> which uses the JDK
<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>
<para><emphasis>Cookies</emphasis></para>
<para>
Basic cookie support is provided by the <emphasis>transfer-cookies</emphasis> attribute on the outbound gateway. When
set to true (default is false), a <emphasis>Set-Cookie</emphasis> header received from the server in a response will be
converted to <emphasis>Cookie</emphasis> in the reply message. This header will then be used
on subsequent sends. This enables simple stateful interactions, such as...
</para>
<para>
<emphasis>...-&gt;logonGateway-&gt;...-&gt;doWorkGateway-&gt;...-&gt;logoffGateway-&gt;...</emphasis>
</para>
<para>
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>
</section>
<section id="http-namespace">
<title>HTTP Namespace Support</title>
<para>
Spring Integration provides an <emphasis>http</emphasis> namespace and
the corresponding schema definition. To include it in your configuration,
simply provide the following namespace declaration in your application
context configuration file:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
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">
...
</beans>]]></programlisting>
<para><emphasis>Inbound</emphasis></para>
<para>
The XML Namespace provides two components for handling HTTP Inbound
requests. In order to process requests without returning a dedicated
response, use the <emphasis>inbound-channel-adapter</emphasis>:
</para>
<programlisting language="xml"><![CDATA[<int-http:inbound-channel-adapter id="httpChannelAdapter" channel="requests"
supported-methods="PUT, DELETE"/>]]></programlisting>
<para>
To process requests that do expect a response, use an
<emphasis>inbound-gateway</emphasis>:
</para>
<programlisting language="xml"><![CDATA[<int-http:inbound-gateway id="inboundGateway"
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>Defining the UriPathHandlerMapping</emphasis></para>
<para>
In order to use the <emphasis>HTTP Inbound Gateway</emphasis> or the
<emphasis>HTTP Inbound Channel Adapter</emphasis> you must define a
<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>
<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>
<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"
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>
<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>
<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
contain the ResponseEntity as long as it's http status is a success (non-successful status codes will throw Exceptions).
If you are expecting a different type, such as a <classname>String</classname>, then provide that fully-qualified class name as shown below.
</para>
<important>
Beginning with Spring Integration 2.1 the <emphasis>request-timeout</emphasis> attribute
of the HTTP Outbound Gateway was renamed to <emphasis>reply-timeout</emphasis>
to better reflect the intent.
</important>
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway id="example"
request-channel="requests"
url="http://localhost/test"
http-method="POST"
extract-request-payload="false"
expected-response-type="java.lang.String"
charset="UTF-8"
request-factory="requestFactory"
reply-timeout="1234"
reply-channel="replies"/>]]></programlisting>
<important>
<para>
Since <emphasis>Spring Integration 2.2</emphasis>, Java serialization
over HTTP is no longer enabled by default. Previously, when setting
the <code>expected-response-type</code>
attribute to a <code>Serializable</code> object, the <code>Accept</code>
header was not properly set up. Since <emphasis>Spring Integration 2.2</emphasis>,
the <classname>SerializingHttpMessageConverter</classname> has now been
updated to set the <code>Accept</code> header to
<code>application/x-java-serialized-object</code>.
</para>
<para>
However, because this could cause incompatibility with existing applications,
it was decided to no longer automatically add this converter to the HTTP endpoints.
If you wish to use Java serialization, you will need to add the
<classname>SerializingHttpMessageConverter</classname> to the appropriate
endpoints, using the <code>message-converters</code> attribute, when using
XML configuration, or using the <code>setMessageConverters()</code> method.
Alternatively, you may wish to consider using JSON instead which is enabled
by simply having <code>Jackson</code> on the classpath.
</para>
</important>
<para>
Beginning with Spring Integration 2.2 you can also determine the HTTP Method dynamically using SpEL and the <emphasis>http-method-expression</emphasis> attribute.
Note that this attribute is obviously murually exclusive with <emphasis>http-method</emphasis>
You can also use <code>expected-response-type-expression</code> attribute instead of <code>expected-response-type</code> and
provide any valid SpEL expression that determines the type of the response.
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway id="example"
request-channel="requests"
url="http://localhost/test"
http-method-expression="headers.httpMethod"
extract-request-payload="false"
expected-response-type-expression="payload"
charset="UTF-8"
request-factory="requestFactory"
reply-timeout="1234"
reply-channel="replies"/>]]></programlisting>
</para>
<para>If your outbound adapter is to be used in a unidirectional way, then you can use an outbound-channel-adapter instead. This means that
a successful response will simply execute without sending any Messages to a reply channel. In the case of any non-successful response
status code, it will throw an exception. The configuration looks very similar to the gateway:
<programlisting language="xml"><![CDATA[<int-http:outbound-channel-adapter id="example"
url="http://localhost/example"
http-method="GET"
channel="requests"
charset="UTF-8"
extract-payload="false"
expected-response-type="java.lang.String"
request-factory="someRequestFactory"
order="3"
auto-startup="false"/>]]></programlisting>
</para>
<note>
<para>
To specify the URL; you can use either the 'url' attribute
or the 'url-expression' attribute. The 'url' is a simple string (with placedholders for
URI variables, as
described below); the 'url-expression' is a SpEL expression, with the Message as the
root object, enabling dynamic urls. The url resulting from the expression evaluation can
still have placeholders for URI variables.
</para>
<para>
In previous releases, some users used the place holders to replace the entire URL with a URI variable.
Changes in Spring 3.1 can cause some issues with escaped characters, such as '?'. For this
reason, it is recommended that if you wish to generate the URL entirely at runtime, you
use the 'url-expression' attribute.
</para>
</note>
<para>
<emphasis>Mapping URI variables</emphasis>
</para>
<para>
If your URL contains URI variables, you can map them using the
<code>uri-variable</code> sub-element. This sub-element is available for the <emphasis>Http Outbound Gateway</emphasis>
and the <emphasis>Http Outbound Channel Adapter</emphasis>.
</para>
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway id="trafficGateway"
url="http://local.yahooapis.com/trafficData?appid=YdnDemo&amp;zip={zipCode}"
request-channel="trafficChannel"
http-method="GET"
expected-response-type="java.lang.String">
<int-http:uri-variable name="zipCode" expression="payload.getZip()"/>
</int-http:outbound-gateway>]]></programlisting>
<para>
The <code>uri-variable</code> sub-element defines two attributes:
<code>name</code> and <code>expression</code>. The <code>name</code> attribute
identifies the name of the URI variable, while the <code>expression</code>
attribute is used to set the actual value. Using the <code>expression</code>
attribute, you can leverage the full power of the Spring Expression Language
(SpEL) which gives you full dynamic access to the message payload and the
message headers. For example, in the above configuration the <code>getZip()</code>
method will be invoked on the payload object of the Message and the result
of that method will be used as the value for the URI variable named 'zipCode'.
</para>
</section>
<section id="http-timeout">
<title>Timeout Handling</title>
<para>
In the context of HTTP components, there are two timing areas that have to be
considered.
</para>
<para>
<itemizedlist>
<listitem>Timeouts when interacting with Spring Integration Channels</listitem>
<listitem>Timeouts when interacting with a remote HTTP server</listitem>
</itemizedlist>
</para>
<para>
First, the components interact with Message Channels, for
which timeouts can be specified. For example, an HTTP Inbound
Gateway will forward messages received from connected HTTP Clients to a
Message Channel (Request Timeout) and consequently the HTTP Inbound Gateway
will receive a reply Message from the Reply Channel (Reply Timeout) that
will be used to generate the HTTP Response. Please see the figure below
for an illustration.
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/http-inbound-gateway-pdf.png" format="PNG" align="center" scalefit="1" width="100%" contentdepth="100%" />
</imageobject>
<imageobject role="html">
<imagedata fileref="images/http-inbound-gateway.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>
How timeout settings apply to an HTTP Inbound Gateway
</para>
</caption>
</mediaobject>
<para>
For outbound endpoints, the second thing to consider is timing while
interacting with the remote server.
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/http-outbound-gateway-pdf.png" format="PNG" align="center" scalefit="1" width="100%" contentdepth="100%" />
</imageobject>
<imageobject role="html">
<imagedata fileref="images/http-outbound-gateway.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>
How timeout settings apply to an HTTP Outbound Gateway
</para>
</caption>
</mediaobject>
<para>
You may want to configure the HTTP related timeout behavior, when
making active HTTP requests using the <emphasis>HTTP Oubound Gateway</emphasis>
or the <emphasis>HTTP Outbound Channel Adapter</emphasis>. In those
instances, these two components use Spring's
<classname><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html">RestTemplate</ulink></classname>
support to execute HTTP requests.
</para>
<para>
In order to configure timeouts for the
<emphasis>HTTP Oubound Gateway</emphasis> and the
<emphasis>HTTP Outbound Channel Adapter</emphasis>, you can either
reference a <classname>RestTemplate</classname> bean directly, using the
<emphasis>rest-template</emphasis> attribute, or you can provide a reference to a
<emphasis><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/http/client/ClientHttpRequestFactory.html">ClientHttpRequestFactory</ulink></emphasis>
bean using the <emphasis>request-factory</emphasis> attribute. Spring provides
the following implementations of the
<interfacename>ClientHttpRequestFactory</interfacename> interface:
</para>
<para>
<classname><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/http/client/SimpleClientHttpRequestFactory.html">SimpleClientHttpRequestFactory</ulink></classname>
- Uses standard J2SE facilities for making HTTP Requests
</para>
<para>
<classname><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.html">HttpComponentsClientHttpRequestFactory</ulink></classname>
- Uses <ulink url="http://hc.apache.org/httpcomponents-client-ga/httpclient/">Apache HttpComponents HttpClient</ulink> (Since Spring 3.1)
</para>
<para>
<classname><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/http/client/CommonsClientHttpRequestFactory.html">ClientHttpRequestFactory</ulink></classname>
- Uses <ulink url="http://hc.apache.org/httpclient-3.x/">Jakarta Commons HttpClient</ulink> (Deprecated as of Spring 3.1)
</para>
<para>
If you don't explicitly configure the <emphasis>request-factory</emphasis>
or <emphasis>rest-template</emphasis> attribute respectively, then a default
RestTemplate which uses a <classname>SimpleClientHttpRequestFactory</classname>
will be instantiated.
</para>
<note>
<para>
With some JVM implementations, the handling of timeouts using
the <emphasis>URLConnection</emphasis> class may not be consistent.
</para>
<para>
E.g. from the <emphasis>Java™ Platform, Standard Edition 6 API Specification</emphasis>
on <emphasis>setConnectTimeout</emphasis>: <quote>Some non-standard
implmentation of this method may ignore the specified timeout. To see
the connect timeout set, please call getConnectTimeout().</quote>
</para>
<para>
Please test your timeouts if you have specific needs. Consider using the
<classname>HttpComponentsClientHttpRequestFactory</classname> which, in turn, uses
<emphasis><ulink url="http://hc.apache.org/httpcomponents-client-ga/">Apache HttpComponents HttpClient</ulink></emphasis>
instead.
</para>
</note>
<para>
Here is an example of how to configure an <emphasis>HTTP Outbound Gateway</emphasis>
using a <classname>SimpleClientHttpRequestFactory</classname>, configured
with connect and read timeouts of 5 seconds respectively:
</para>
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway url="http://www.google.com/ig/api?weather={city}"
http-method="GET"
expected-response-type="java.lang.String"
request-factory="requestFactory"
request-channel="requestChannel"
reply-channel="replyChannel">
<int-http:uri-variable name="city" expression="payload"/>
</int-http:outbound-gateway>
<bean id="requestFactory"
class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="connectTimeout" value="5000"/>
<property name="readTimeout" value="5000"/>
</bean>]]></programlisting>
<para><emphasis>HTTP Outbound Gateway</emphasis></para>
<para>
For the <emphasis>HTTP Outbound Gateway</emphasis>, the XML Schema defines
only the <emphasis>reply-timeout</emphasis>. The <emphasis>reply-timeout</emphasis>
maps to the <emphasis>sendTimeout</emphasis> property of the
<emphasis>org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler</emphasis>
class. More precisely, the property is set on the extended
<classname>AbstractReplyProducingMessageHandler</classname> class, which
ultimatelly sets the property on the <emphasis>MessagingTemplate</emphasis>.
</para>
<para>
The value of the <emphasis>sendTimeout</emphasis> property defaults to "-1"
and will be applied to the connected <interfacename>MessageChannel</interfacename>.
This means, that depending on the implementation, the Message Channel's
<emphasis>send</emphasis> method may block indefinitely. Furthermore,
the <emphasis>sendTimeout</emphasis> property is only used, when the
actual MessageChannel implementation has a blocking send (such as 'full' bounded QueueChannel).
</para>
<para><emphasis>HTTP Inbound Gateway</emphasis></para>
<para>
For the <emphasis>HTTP Inbound Gateway</emphasis>, the XML Schema defines
the <emphasis>request-timeout</emphasis> attribute, which will be used
to set the <emphasis>requestTimeout</emphasis> property on the
<classname>HttpRequestHandlingMessagingGateway</classname> class
(on the extended MessagingGatewaySupport class). Secondly, the
<emphasis>reply-timeout</emphasis> attribute exists and it maps to the
<emphasis>replyTimeout</emphasis> property on the same class.
</para>
<para>
The default for both timeout properties is "1000ms". Ultimately, the
<emphasis>request-timeout</emphasis> property will be used to set the
<emphasis>sendTimeout</emphasis> on the used <classname>MessagingTemplate</classname>
instance. The <emphasis>replyTimeout</emphasis> property on the other
hand, will be used to set the <emphasis>receiveTimeout</emphasis>
property on the used <classname>MessagingTemplate</classname> instance.
</para>
<tip>
In order to simulate connection timeouts, connect to a non-routable IP
address, for example 10.255.255.10.
</tip>
</section>
<section id="http-proxy">
<title>HTTP Proxy configuration</title>
<para>
If you are behind a proxy and need to configure proxy settings for HTTP outbound adapters and/or
gateways, you can apply one of two approaches. In most cases, you can rely on the standard Java
System Properties that control the proxy settings. Otherwise, you can explicitly configure a
Spring bean for the HTTP client request factory instance.
</para>
<para>
<emphasis>Standard Java Proxy configuration</emphasis>
</para>
<para>
There are 3 System Properties you can set to configure the proxy settings that will be used by the HTTP protocol handler:
<itemizedlist>
<listitem>
<para><emphasis>http.proxyHost</emphasis> - the host name of the proxy server. </para>
</listitem>
<listitem>
<para><emphasis>http.proxyPort</emphasis> - the port number, the default value being 80. </para>
</listitem>
<listitem>
<para><emphasis>http.nonProxyHosts</emphasis> - a list of hosts that should be reached directly,
bypassing the proxy. This is a list of patterns separated by '|'. The patterns may start or end with a '*' for wildcards. Any host matching one of these patterns will be reached through a direct connection instead of through a proxy. </para>
</listitem>
</itemizedlist>
And for HTTPS:
<itemizedlist>
<listitem>
<para><emphasis>https.proxyHost</emphasis> - the host name of the proxy server. </para>
</listitem>
<listitem>
<para><emphasis>https.proxyPort</emphasis> - the port number, the default value being 80. </para>
</listitem>
</itemizedlist>
For more information please refer to this document: http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
</para>
<para>
<emphasis>Spring's SimpleClientHttpRequestFactory</emphasis>
</para>
<para>
If for any reason, you need more explicit control over the proxy configuration, you can use Spring's
<classname>SimpleClientHttpRequestFactory</classname> and configure its 'proxy' property as such:
<programlisting language="xml"><![CDATA[<bean id="requestFactory"
class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="proxy">
<bean id="proxy" class="java.net.Proxy">
<constructor-arg>
<util:constant static-field="java.net.Proxy.Type.HTTP"/>
</constructor-arg>
<constructor-arg>
<bean class="java.net.InetSocketAddress">
<constructor-arg value="123.0.0.1"/>
<constructor-arg value="8080"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>]]></programlisting>
</para>
</section>
<section id="http-header-mapping">
<title> HTTP Header Mappings</title>
<para>
Spring Integration provides support for Http Header mapping for both HTTP Request and HTTP Responses.
</para>
<para>
By default all standard Http Headers as defined here
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields will be mapped from the message to HTTP request/response headers without
further configuration.
However if you do need further customization you may provide additional configuration via convenient namespace support.
You can provide a comma-separated list of header names, and you can also include simple patterns with the '*' character acting as a wildcard.
If you do provide such values, it will override the default behavior. Basically, it assumes you are in complete control at that point.
However, if you do want to include all of the standard HTTP headers, you can use the shortcut patterns: HTTP_REQUEST_HEADERS and
HTTP_RESPONSE_HEADERS. Here are some examples:
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway id="httpGateway"
url="http://localhost/test2"
mapped-request-headers="foo, bar"
mapped-response-headers="X-*, HTTP_RESPONSE_HEADERS"
channel="someChannel"/>
<int-http:outbound-channel-adapter id="httpAdapter"
url="http://localhost/test2"
mapped-request-headers="foo, bar, HTTP_REQUEST_HEADERS"
channel="someChannel"/>]]></programlisting>
The adapters and gateways will use the <classname>DefaultHttpHeaderMapper</classname> which now provides
two static factory methods for "inbound" and "outbound" adapters so that the proper direction can be
applied (mapping HTTP requests/responses IN/OUT as appropriate).
</para>
<para>
If further customization is required you can also configure a <classname>DefaultHttpHeaderMapper</classname> independently
and inject it into the adapter via the <code>header-mapper</code> attribute.
<programlisting language="xml"><![CDATA[<int-http:outbound-gateway id="httpGateway"
url="http://localhost/test2"
header-mapper="headerMapper"
channel="someChannel"/>
<bean id="headerMapper" class="o.s.i.http.support.DefaultHttpHeaderMapper">
<property name="inboundHeaderNames" value="foo*, *bar, baz"/>
<property name="outboundHeaderNames" value="a*b, d"/>
</bean>]]></programlisting>
</para>
<para>Of course, you can even implement the HeaderMapper strategy interface directly and provide a reference to that
if you need to do something other than what the <classname>DefaultHttpHeaderMapper</classname> supports.</para>
</section>
<section id="http-samples">
<title>HTTP Samples</title>
<section id="multipart-rest-inbound">
<title>Multipart HTTP request - RestTemplate (client) and Http Inbound Gateway (server)</title>
<para>
This example demonstrates how simple it is to send a Multipart HTTP request via Spring's RestTemplate and receive
it with a Spring Integration HTTP Inbound Adapter. All we are doing is creating a <classname>MultiValueMap</classname> and
populating it with multi-part data. The <classname>RestTemplate</classname> will take care of the rest (no pun intended) by
converting it to a <classname>MultipartHttpServletRequest</classname> . This particular client will send a multipart HTTP Request
which contains the name of the company as well as an image file with the company logo.
<programlisting language="java"><![CDATA[RestTemplate template = new RestTemplate();
String uri = "http://localhost:8080/multipart-http/inboundAdapter.htm";
Resource s2logo = 
new ClassPathResource("org/springframework/samples/multipart/spring09_logo.png");
MultiValueMap map = new LinkedMultiValueMap();
map.add("company", "SpringSource");
map.add("company-logo", s2logo);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("multipart", "form-data"));
HttpEntity request = new HttpEntity(map, headers);
ResponseEntity<?> httpResponse = template.exchange(uri, HttpMethod.POST, request, null);]]></programlisting>
</para>
<para>
That is all for the client.
</para>
<para>
On the server side we have the following configuration:
<programlisting language="xml"><![CDATA[<int-http:inbound-channel-adapter id="httpInboundAdapter"
channel="receiveChannel"
name="/inboundAdapter.htm"
supported-methods="GET, POST"/>
<int:channel id="receiveChannel"/>
<int:service-activator input-channel="receiveChannel">
<bean class="org.springframework.integration.samples.multipart.MultipartReceiver"/>
</int:service-activator>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>]]></programlisting>
</para>
<para>
The 'httpInboundAdapter' will receive the request, convert it to a <classname>Message</classname> with a payload
that is a <classname>LinkedMultiValueMap</classname>. We then are parsing that in the 'multipartReceiver' service-activator;
<programlisting language="java"><![CDATA[public void receive(LinkedMultiValueMap<String, Object> multipartRequest){
System.out.println("### Successfully received multipart request ###");
for (String elementName : multipartRequest.keySet()) {
if (elementName.equals("company")){
System.out.println("\t" + elementName + " - " +
((String[]) multipartRequest.getFirst("company"))[0]);
}
else if (elementName.equals("company-logo")){
System.out.println("\t" + elementName + " - as UploadedMultipartFile: " +
((UploadedMultipartFile) multipartRequest
.getFirst("company-logo")).getOriginalFilename());
}
}
}
]]></programlisting>
You should see the following output:
<programlisting language="xml"><![CDATA[### Successfully received multipart request ###
company - SpringSource
company-logo - as UploadedMultipartFile: spring09_logo.png]]></programlisting>
</para>
</section>
</section>
</chapter>