Sunday, September 16, 2012

Java: Spring Framework 2.x Remoting Support

Welcome to my first post after my wedding vacation. In this post i will introduce Spring's support for various remoting technologies, such as RMI, Hessian, Burlap, HTTP Invoker, and Web Services.

I will introduce Spring Web Services in a another post, but in this post i will briefly explain the other techniques.

Table of Contents

  • Introduction
  • Spring RMI "Remote Method Invocation" support
    • Exposing an RMI service
    • Invoking an RMI service
  • Spring Exposing/Invoking services through HTTP
    • Hessian
    • Burlap
  • Conclusion
  • References
Introduction

Remoting is a key technology in developing distributed applications, especially multitier enterprise applications. It allows different applications, or components running on different JVMs or on different machines to communicate and work together using a specific protocol.

Spring RMI "Remote Method Invocation" support

RMI is a java based remoting technology that allows two java applications running on different JVMs and/or machines to communicate with each other. With RMI an object can call the methods of another remote object. RMI relies on object serialization to marshal and unmarshal method arguments and return values.

Suppose you would like to expose a weather service as an RMI service. To use Spring’s remoting facilities for this purpose, create a bean configuration file such as rmi-server.xml in the classpath root to define the service. In this file, you declare a bean for the weather service implementation and export it as an RMI service by using RmiServiceExporter.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="weatherService"
class="com.example.WeatherServiceImpl" />
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="WeatherService" />
<property name="serviceInterface"
value="com.example.WeatherService" />
<property name="service" ref="weatherService" />
</bean>
</beans>

In the rmi-server.xml example we have two beans configured one of them is a simple weather service bean, and the other one is to export this bean as RMI service using RMIServiceExporter. In the second bean we have different properties such as serviceName to configure the service name, and serviceInterface that is the interface of the implemented service, and the service property that references the actual service.

By default, RmiServiceExporter attempts to look up an RMI registry at localhost port 1099. If it can’t find the RMI registry, it will start a new one. However, if you would like to bind your service to another running RMI registry, you can specify the host and port of that registry in the registryHost and registryPort properties. Note that once you specify the registry host, RmiServiceExporter will not start a new registry, even if the specified registry doesn’t exist.
To start a server that provides the RMI weather service, run the following class to create an application context for the preceding bean configuration file:

public class RmiServer {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("rmi-server.xml");
}
}

In a client environment you can use RmiProxyFactoryBean to create a proxy for the remote service and you can use this service as if it were a local bean. By setting the serviceUrl property of the RmiProxyFactoryBean to "rmi://localhost:1099/WeatherService" and serviceInterface property to "com.example.rmi.WeatherService" you will be able to use this service locally.

Spring Exposing/Invoking services through HTTP

As RMI communicates over its own protocol, which may not be able to pass through firewalls, you would like to expose a service from your Java application for clients to invoke over HTTP, which is allowed to pass through most firewalls.

Hessian and Burlap are two simple lightweight remoting technologies developed by Caucho Technology. They both communicate using proprietary messages over HTTP and have their own serialization mechanism, but they are much simpler than web services. The only difference between them is that Hessian communicates using binary messages while Burlap communicates using XML messages.

In addition to the preceding two technologies, the Spring framework itself also offers a remoting technology called HTTP Invoker. It also communicates over HTTP, but uses Java’s object serialization mechanism to serialize objects. Unlike Hessian and Burlap, HTTP Invoker requires both sides of a service to be running on the Java platform and using the Spring framework. However, it can serialize all kinds of Java objects, some of which may not be serialized by Hessian/Burlap’s proprietary mechanism.

To expose a Hessian service with Spring, you have to create a web application using Spring MVC "Include hessian.jar".

To expose our WhetherService as a Hessian service using HessianServiceExporter.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="weatherService"
class="com.example.WeatherServiceImpl" /> 
<bean name="/WeatherService"
class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="weatherService" />
<property name="serviceInterface"
value="com.example.WeatherService" />
</bean>
</beans> 

In a client environment you can use HessianProxyFactoryBean to create a proxy for the remote service and you can use this service as if it were a local bean. By setting the serviceUrl property of the HessianProxyFactoryBean to "rmi://localhost:1099/WeatherService" and serviceInterface property to "com.example.rmi.WeatherService" you will be able to use this service locally.

To expose a Burlap service use BurlapServiceExporter and to invoke it use BurlapProxyFactoryBean instead.

To expose a service using spring HTTP Invoker you need to use HttpInvokerServiceExporter and HttpInvokerProxyFactoryBean.

Conclusion

In this post, you have learned how to expose and invoke remote services with Spring’s remoting support. Spring builds in support for many remoting technologies, such as RMI, Hessian, Burlap, and HTTP Invoker.

Spring’s remoting support is consistent across different remoting technologies. On the server side, Spring allows you to expose an arbitrary bean as a remote service through a service exporter. On the client side, Spring provides various proxy factory beans for you to create a local proxy for a remote service, so that you can use the remote service as if it were a local bean.

In the next post i will introduce Spring Web Services which is a yet another way for our applications to support remoting.

References