Remoting Spring – RMI and Http

Another very useful feature of spring framework is the support for remote calling. In distributed solutions (typical client-server) this is a good solution and quite easy to achieve.

In this article I’d like to show you two differents systems of remote calling. These are Remote Method Invocation (RMI) and Spring’s HTTP invoker.

For this purpose, I used an example divided in two parts. Server and client application.

The server application is hosted on a Web application. In application Context I defined both communication endpoint, rmi:// and http://. The client will be able to call either urls.

Take a look at applicationContext.xml


<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="orderService" class="it.remotespring.OrderServiceImpl" />

	<bean name="orderExporter"
		class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
		<property name="service" ref="orderService" />
		<property name="serviceInterface" value="it.remotespring.OrderService" />
	</bean>

	<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
		<!-- does not necessarily have to be the same name as the bean to be exported -->
		<property name="serviceName" value="OrderService" />
		<property name="service" ref="orderService" />
		<property name="serviceInterface" value="it.remotespring.OrderService" />
		<!-- defaults to 1099 -->
		<property name="registryPort" value="1199" />
	</bean>

</beans>

The web application accepts requests from http://<host>/remoting/OrderService and rmi://<host>:1199/OrderService

This is the client spring configuration file:


<?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:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

	<bean id="HttpOrderProxyService"
		class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
		<property name="serviceUrl">
			<value>http://localhost:8080/RemotingSpring/remoting/OrderService
			</value>
		</property>
		<property name="serviceInterface">
			<value>it.remotespring.OrderService</value>
		</property>
	</bean>

	<bean class="it.remotingspringclient.rmi.Proxy" id="Proxy">
		<property name="orderService" ref="RmiOrderService" />
	</bean>
	<bean id="RmiOrderService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
		<property name="serviceUrl" value="rmi://localhost:1199/OrderService" />
		<property name="serviceInterface" value="it.remotespring.OrderService" />
	</bean>

</beans>

Before continuing, this is the Order Bean. Take a note that it must be serializable:


package it.remotespring;

import java.io.Serializable;
import java.util.Date;
public class Order implements Serializable {

 /**
  *
  */
 private static final long serialVersionUID = 1L;
 private String orderId;
 private double invoice;
 private int itemNumber;
 private Date shippingDate;
 
 public Order()
 {}
 
 public Order(String orderId, double invoice, int itemNumber)
 {
  this.orderId = orderId;
  this.invoice = invoice;
  this.itemNumber = itemNumber;    
 }

 public String getOrderId() {
  return orderId;
 }
 public void setOrderId(String orderId) {
  this.orderId = orderId;
 }
 public double getInvoice() {
  return invoice;
 }
 public void setInvoice(double invoice) {
  this.invoice = invoice;
 }
 public int getItemNumber() {
  return itemNumber;
 }
 public void setItemNumber(int itemNumber) {
  this.itemNumber = itemNumber;
 }

 public Date getShippingDate() {
  return shippingDate;
 }

 public void setShippingDate(Date shippingDate) {
  this.shippingDate = shippingDate;
 }
 
 @Override
 public String toString()
 {
  return " orderId:" + orderId +
    " itemNumber:" + itemNumber +
    " invoice:" + invoice +
    " shippingDate:" + shippingDate;
 }

}

The OrderService interface:


package it.remotespring;

public interface OrderService {
 
 public void Check(Order order) throws Exception;

 public Order Process(Order order);

 public Order Shipping(Order order);

}

And its implementation:


package it.remotespring;

import java.util.Date;

public class OrderServiceImpl implements OrderService{

 @Override
 public void Check(Order order) throws Exception{
  if (order.getItemNumber()==0)
  {
   throw new Exception("Quantity cannot be 0!!");
  }  
 }

 @Override
 public Order Process(Order order) {
  order.setInvoice(order.getItemNumber() * 1.3);
  return order;
 }

 @Override
 public Order Shipping(Order order) {
  order.setShippingDate(new Date());
  return order;
 }

}

Now the client part. That is a Java application with two main classes. For http client (the client which consumes the http server endpoint) the connection is by http protocol:


package it.remotingspringclient.http;
import it.remotespring.Order;
import it.remotespring.OrderService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HttpClient {
 /**
  * @param args
  * @throws Exception
  */
 public static void main(String[] args) throws Exception {
  final ApplicationContext context = new ClassPathXmlApplicationContext(
    "/client-config.xml");
  final OrderService orderService = (OrderService)
    context.getBean("HttpOrderProxyService");
  Order order = new Order("CZ-2634", 0, 123);
  orderService.Check(order);
  order = orderService.Process(order);
  order = orderService.Shipping(order);
  System.out.println(order);
 }
}

The process is very easy and I wouldn’t spend any time to explain it. Briefly, the order is processed and added with Invoice properties and Shipping Date.

For Rmi client the process is the same of the previous.


package it.remotingspringclient.rmi;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class RmiClient {
 public static void main(String[] args) throws Exception {
  final ApplicationContext context = new ClassPathXmlApplicationContext(
    "/client-config.xml");

  final Proxy proxy = (Proxy) context.getBean("Proxy");

  proxy.execute();

 }
}

and this is the proxy class.


package it.remotingspringclient.rmi;

import it.remotespring.Order;
import it.remotespring.OrderService;

public class Proxy {

 private OrderService orderService;

 public void execute() throws Exception {
  Order order = new Order("CZ-2634", 0, 123);

  getOrderService().Check(order);
  order = getOrderService().Process(order);
  order = getOrderService().Shipping(order);

  System.out.println(order);
 }

 public OrderService getOrderService() {
  return orderService;
 }

 public void setOrderService(OrderService orderService) {
  this.orderService = orderService;
 }

}

In conclusion you can choose different protocol to access a remote resource. The use of one or other depends only by your configuration and, most important, you don’t have to change any lines of codes.

A good resource is spring official guide available at this link http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/remoting.html

About these ads

4 thoughts on “Remoting Spring – RMI and Http

    • I agree with your opinion, only remember that Enterprise Java Bean is a technology standard and rmi is a protocol communication. You can use Ejb and Rmi in the same project (I did it) with very good result but, in some product’s enviroment, you can’t use it because, due to company policy, the rmi ports are often closed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s