In my previous blog entry I briefly mentioned a couple of lightweight remoting protocols, Hessian and Burlap, that are great alternatives when you only need to make simple remote method calls between Java processes and do not need to concern yourself with interoperability issues.
Both Hessian and Burlap have been developed and released by Caucho Technology, makers of the Resin application server. Both use HTTP as their transport mechanism. Whereas Hessian is a slim binary protocol, Burlap is a slim XML-based protocol.
Hessian (or Burlap) services are traditionally defined as servlets in web.xml, using Caucho’s prebuilt HessianServlet (or BurlapServlet) class, respectively. The application service to be exported is either implemented as a subclass of such a servlet or as a plain Java class (POJO) implementing the service interface. On the client side, Hessian and Burlap provide factory classes that generate a proxy for a specific service interface and target URL.
Hessian and Burlap use their own serialization algorithms for primitive types, collections, and so on. It allows for loose coupling between loosely related Java processes (in some cases even different languages). However, there are some limitations to their serialization mechanism. Because of the need to rebuild an object’s fields through reflection, Hessian and Burlap are not able to deserialize a state that is held in final instance variables. In addition, they are not able to detect objects with customized serialization – for example, Hibernate collections.
Unfortunately, for the particular problem I had at hand, Hessian (or Burlap) did not fit the bill as I was using Hibernate for the persistence layer and would have run into one of the Hessian’s serialization limitations.
Spring to the Rescue: HTTP Invoker
The other alternative I wanted to consider was to take full advantage of the Java serialization mechanism to stream objects back and forth over an HTTP tunnel. I did not want to create a whole infrastructure for doing this. Fortunately, Spring provides this infrastructure for me called HTTP Invoker.
Spring offers the HTTP Invoker remoting strategy as a direct alternative to Hessian and Burlap. Instead of the custom serialization found in Hessian/Burlap, HTTP Invoker uses Java serialization, just like RMI.
As always there are some tradeoffs. Because HTTP Invoker is only available in Spring, both the client side and the server side need to be based on Spring.
The two main classes of Spring’s HTTP Invoker are:
- org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
- org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
Follow these simple steps to export and access a service using Spring’s HTTP Invoker.
1. Exporting the Service
a) Define a Service Interface and POJO implementation
public interface OrderService {
Order getOrder(int orderId);
}
class OrderServiceImpl implements OrderService {
Order getOrder(int orderId) {
// do something here
}
}
b) Server Configuration
Exporting an existing Spring-managed bean as an HTTP invoker service is straightforward. A corresponding service exporter is defined as a Spring Controller in a Spring web MVC context.
<bean id="orderService" class=”OrderServiceImpl”/>
<bean name="/OrderService-httpinvoker" class="org.sprfr.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="orderService"/>
<property name="serviceInterface" value="OrderService"/>
</bean>
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 the web application where the service is defined is available at http://localhost:8080/myapp, the remote OrderService end-point would be available at http://localhost:8080/myapp/remoting/OrderService-httpinvoker.
2. Accessing the Service
a) Client Configuration
On the client side a proxy for a target service can be created via a Spring bean definition as follows:
<bean id="ordeServiceHttpInvokerProxy" class="org.sprfr.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/myapp/remoting/OrderService-httpinvoker"/>
<property name="serviceInterface" value="OrderService"/>
</bean>
<bean id=”myOrderServiceClient” class=”MyOrderServiceClient”>
<property name=”orderService” ref=” ordeServiceHttpInvokerProxy”/>
</bean>
b) Client Code
The client code consists of a class that exposes a bean property of type “OrderService”. This way the client is not tied to a remote service but rather to a plain Java interface.
Public class MyOrderServiceClient {
Private OrderService orderService;
Public void setOrderService(OrderService orderService) {
This.orderService = orderService;
}
public void doSomething() {
Order order = orderService.getOrder(…);
…
}
}
Concluding Remarks:
If you are already using the Spring framework in your application (or are considering it), and have a need to perform method invocations on a remote service, and there are no interoperability requirements to speak of (i.e., there is no need for a WSDL/SOAP stack), then consider using Spring’s HTTP Invoker as your “lightweight remoting” alternative. It’s really that simple.
References:
http://www.caucho.com/resin-3.0/protocols/hessian.xtp
http://www.caucho.com/resin-3.0/protocols/burlap.xtp
http://www.springframework.org/documentation
Comments
This was handy for me. Thanks for taking the time to post.
how does using http invoker helped with hibernate LazyInitializationException isn't that the same story like with hessian?
I know the post is from 2006...:)
You could write your own com.caucho.hessian.io.Serializer/Deserializer for your non standart objects.
I needed to develop a client/server rich application with swing and I already used spring for IoC and AOP. Your post was very helpful. In a few hours my local applications was converted to a client/server application. Spring is really amazing!
hi,
here is a link to a complete eclipse rcp applicaton using spring remoting. http://www.devx.com/Java/Article/31763/0/page/1 . Complete code is also given by the author Mr.Stephen Lum. You can import the project to eclipse, deploy the application in tomcat. Be aware to deploy the application to a directory whose path doesnt contain white spaces or u will get an error something like bad protocol. better use a context xml file in "\conf\Catalina\localhost" of tomcat. a sample content of the context xml file(if u dont know it) is given here.
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="E:/workspace/StockTraderServer/WebRoot"
path="/stocktradeserver" reloadable="true" workDir="work\Catalina\localhost\stocktradeserver">
</Context>
regards, prajeesh
Hi,
I am fairly new to spring and I found your example to be great for spring remoting. Do you by any chance have a complete example for spring remoting. I havent been able to get it working in my application and I believe its due to wrong configurations. Any help would be appreciated.
Thanks!!
Post new comment