Professional Java Development with the Spring Framework
As a direct alternative to Hessian and Burlap, Spring offers the HTTP invoker remoting strategy. Instead of the custom serialization found in Hessian and Burlap, HTTP invoker uses Java serialization — just like RMI. Applications can rely on full serialization power, as long as all transferred objects properly follow Java serialization rules (implementing the java.io.Serializable marker interface and properly defining serialVersionUID if necessary).
The main classes of Spring's HTTP invoker are:
-
org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean: Proxy factory for Spring-compliant proxies that communicate with backend HTTP invoker services. To be defined in a Spring bean factory or application context, exposing the proxy object for references (through the FactoryBean mechanism). Proxies will throw Spring's generic RemoteAccessException in case of remote invocation failure.
-
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter: Exporter implemented as Controller for Spring's web MVC framework. Can take any existing Spring- managed bean and export it at a given HTTP URL, allowing the target bean to be fully configured and wired via Spring. The same target bean can easily be exported through HTTP invoker and other protocols (such as Hessian and Burlap) at the same time, at different URLs.
These classes are direct equivalents of HessianProxyFactoryBean and HessianServiceExporter and BurlapProxyFactoryBean and BurlapServiceExporter, respectively. They can be considered as drop-in replacements, as they share the same configuration style and behavior.
Because of the nature of HTTP invoker (which is available only in Spring), both the client side and the server side need to be based on Spring — and on Java in the first place because of the use of Java serialization. In contrast to Hessian and Burlap, there is no option for cross-platform remoting. HTTP invoker is clearly dedicated to powerful and seamless Java-to-Java remoting.
A further difference to Hessian and Burlap is the tight coupling of client and server codebases. Java serialization requires strictly matching versions of the involved classes at both ends. If the application versions on the client and server side differ, use of serialVersionUID is required. (See the documentation on Java serialization for details.)
Important | HTTP invoker is a powerful option for Java-to-Java remoting, which uses Java serialization and offers the same serialization power as RMI. Consider Hessian as a loosely coupled alternative to HTTP invoker. Both are binary and roughly equivalent in terms of efficiency. Their major difference is the serialization mechanism: HTTP invoker uses standard Java serialization; Hessian uses its own serialization mechanism. Setup and maintenance is as easy as with Hessian and Burlap. The only stricter requirement is that the class versions at both ends have to be compatible — a consequence of using Java serialization. |
Accessing a Service
On the client side, a proxy for a target service can easily be created via a Spring bean definition — analogous to Hessian and Burlap. The configuration needed is the proxy factory class name, the HTTP URL of the target service, and the service interface to expose. For example:
<bean > <property name="serviceUrl"> <value>http://localhost:8080/remoting/OrderService-httpinvoker</value> </property> <property name="serviceInterface"> <value>org.springframework.samples.jpetstore.domain.logic.OrderService</value> </property> </bean>
The service interface is the same plain Java business interface used in the Hessian/Burlap example. It does not derive from specific base interfaces or throw special remoting exceptions:
public interface OrderService { Order getOrder(int orderId); }
Such a proxy is then available for bean references; for example:
<bean > <property name="orderService"> <ref bean="httpInvokerProxy"/> </property> </bean>
The MyOrderServiceClient class is the same as in the Hessian/Burlap example. It would simply expose a bean property of type org.springframework.samples.jpetstore.domain.logic.OrderService here, so the client is not tied to a remote service but rather to a plain Java business interface:
public class MyOrderServiceClient { private OrderService orderService; public void setOrderService(OrderService orderService) { this.orderService = orderService; } public void doSomething() { Order order = this.orderService.getOrder(...); ... } }
Switching between an HTTP invoker proxy and a Hessian proxy for our OrderService simply involves redefining the proxy from HttpInvokerProxyFactoryBean to HessianProxyFactoryBean. Through the use of a placeholder, this can even be driven from outside an XML bean definition file; see the example in the "Hessian and Burlap" section for an illustration.
Important | As outlined in the discussion of Hessian and Burlap, switching between different remoting protocols is a configuration matter. This also applies to HTTP invoker. It can be considered a drop-in replacement for Hessian or Burlap, as long as all transferred objects properly support Java serialization. Configuration-wise, only the class name of the proxy factory will change. |
Exporting a Service
On the server side, exporting an existing Spring-managed bean as an HTTP invoker service is straightforward. A corresponding service exporter needs to be defined as Spring Controller in a Spring web MVC context. As discussed in the section on Hessian and Burlap, it is usually advisable to define such exporters in a separate DispatcherServlet with its own context. For example, the following code exposes the petStore bean in the root application context as HTTP invoker service:
<bean name="/OrderService-httpinvoker" > <property name="service"> <ref bean="petStore"/> </property> <property name="serviceInterface"> <value>org.springframework.samples.jpetstore.domain.logic.OrderService</value> </property> </bean>
As with Hessian and Burlap, such an exporter could be defined in the remoting-servlet.xml context file of a DispatcherServlet called remoting. The corresponding web.xml entries would look like this:
<servlet> <servlet-name>remoting</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup/> </servlet> <servlet-mapping> <servlet-name>remoting</servlet-name> <url-pattern>/remoting/*</url-pattern> </servlet-mapping>
Assuming that the server is available at http://localhost:8080, the remote OrderService would then be available as HTTP invoker service at http://localhost:8080/remoting/OrderServicehttpinvoker.
The same DispatcherServlet could be used for exporting an HTTP invoker service and Hessian and Burlap services. It would simply define one exporter per remoting protocol, each available at a distinct URL. This is effectively the case in the JPetStore sample application, from which all examples in this chapter originate.
Important | An HTTP invoker endpoint can seamlessly coexist with Hessian and Burlap endpoints, even in the same dispatcher. The client chooses a specific endpoint through the URL that it talks to, as discussed in the section on Hessian and Burlap. |
Customization Options
HTTP invoker uses Spring's generic remote invocation mechanism underneath, serializing org.springframework.remoting.support.RemoteInvocation and org.springframework.remoting.support.RemoteInvocationResult objects.
The standard configuration is sufficient for typical needs, where no additional invocation attributes have to be passed along. However, if, for example, a user credential attribute should be included in the invocation, a custom org.springframework.remoting.support.RemoteInvocationFactory can be implemented and registered with the HttpInvokerProxyFactoryBean. A corresponding customorg.springframework.remoting.support.RemoteInvocationExecutor, to be registered with the HttpInvokerServiceExporter, will apply such additional attributes on the server side, for example performing authorization checks. This can also be provided out-of-the-box by Spring extension libraries.
Note that the remote invocation infrastructure is shared with the RMI invoker, discussed later in this chapter. A custom RemoteInvocationFactory / RemoteInvocationExecutor pair can be applied to either HTTP invoker or RMI invoker without changes, transferring the additional attributes over the respective protocol.
Secure communication via SSL is straightforward, as with Hessian and Burlap: Simply specify an HTTPS URL as a service URL. Alternatively, you can also implement your own encryption mechanism as a custom RemoteInvocationFactory / RemoteInvocationExecutor pair, sharing the encryption mechanism with RMI invoker.
A further customization option is the org.springframework.remoting.httpinvoker.HttpInvokerRequestExecutor strategy, which is responsible for the actual generation of the HTTP request for a given invocation. The default implementation, org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor, uses a standard java.net.URLConnection for sending and receiving. As an alternative, Spring also provides org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor, which delegates to Jakarta's Commons HttpClient (http://jakarta.apache.org/commons/httpclient), allowing for HTTP-based authentication and other advanced uses of HTTP.
Important | HTTP invoker is highly customizable through the RemoteInvocationFactory, RemoteInvocationExecutor, and HttpInvokerRequestExecutor strategies. However, for typical needs, you don't have to worry about any of this. The standard configuration of HttpInvokerProxyFactoryBean and HttpInvokerService Exporter should be perfectly sufficient. |