Spring HTTP Invoker

As opposed to Hessian, Spring HTTP invokers are both lightweight protocols that use their own slim serialization mechanisms and use the standard Java serialization mechanism to expose services through HTTP. This has a huge advantage if your arguments and return types are complex types that cannot be serialized by using the serialization mechanisms Hessian uses (see the next section for more considerations when you choose a remoting technology).

Under the hood, Spring uses either the standard facilities provided by the JDK or Apache HttpComponents to perform HTTP calls. If you need more advanced and easier-to-use functionality, use the latter. See hc.apache.org/httpcomponents-client-ga/ for more information.

Be aware of vulnerabilities due to unsafe Java deserialization: Manipulated input streams can lead to unwanted code execution on the server during the deserialization step. As a consequence, do not expose HTTP invoker endpoints to untrusted clients. Rather, expose them only between your own services. In general, we strongly recommend using any other message format (such as JSON) instead.

If you are concerned about security vulnerabilities due to Java serialization, consider the general-purpose serialization filter mechanism at the core JVM level, originally developed for JDK 9 but backported to JDK 8, 7 and 6 in the meantime. See https://blogs.oracle.com/java-platform-group/entry/incoming_filter_serialization_data_a and https://openjdk.java.net/jeps/290.

Exposing the Service Object

Setting up the HTTP invoker infrastructure for a service object closely resembles the way you would do the same by using Hessian. As Hessian support provides HessianServiceExporter, Spring’s HttpInvoker support provides org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter.

To expose the AccountService (mentioned earlier) within a Spring Web MVC DispatcherServlet, the following configuration needs to be in place in the dispatcher’s application context, as the following example shows:

<bean name="/AccountService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
	<property name="service" ref="accountService"/>
	<property name="serviceInterface" value="example.AccountService"/>
</bean>

Such an exporter definition is exposed through the DispatcherServlet instance’s standard mapping facilities, as explained in the section on Hessian.

Alternatively, you can create an HttpInvokerServiceExporter in your root application context (for example, in 'WEB-INF/applicationContext.xml'), as the following example shows:

<bean name="accountExporter" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
	<property name="service" ref="accountService"/>
	<property name="serviceInterface" value="example.AccountService"/>
</bean>

In addition, you can define a corresponding servlet for this exporter in web.xml, with the servlet name matching the bean name of the target exporter, as the following example shows:

<servlet>
	<servlet-name>accountExporter</servlet-name>
	<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>accountExporter</servlet-name>
	<url-pattern>/remoting/AccountService</url-pattern>
</servlet-mapping>

Linking in the Service at the Client

Again, linking in the service from the client much resembles the way you would do it when you use Hessian. By using a proxy, Spring can translate your calls to HTTP POST requests to the URL that points to the exported service. The following example shows how to configure this arrangement:

<bean id="httpInvokerProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
	<property name="serviceUrl" value="https://remotehost:8080/remoting/AccountService"/>
	<property name="serviceInterface" value="example.AccountService"/>
</bean>

As mentioned earlier, you can choose what HTTP client you want to use. By default, the HttpInvokerProxy uses the JDK’s HTTP functionality, but you can also use the Apache HttpComponents client by setting the httpInvokerRequestExecutor property. The following example shows how to do so:

<property name="httpInvokerRequestExecutor">
	<bean class="org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor"/>
</property>