Remote access with Spring HttpInvoker

Introduction

I can remember the early days of Java where I used RMI to create distributed system. But it is very difficult to use RMI these days because distributed communication is restricted due to the security concerns under the organizational policies. Enterprise applications are evolved to adapt to current environment but for small scale distributed systems are not possible. This fact mainly forced me to explore the new technologies which is best suit for my requirements which are listed below

  • Enterprise applications are mainly depends on HTTP protocols. Therefore, my choice also  HTTP. The RMI communication protocol is JRMP, but over the network, there are lot of problems communicating via JRMP. The best use is pure HTTP protocol without any tunneling because which can cause to firewall problems.
  • The Framework should support to send and receive Java serialized objects  over the chosen protocols (which is HTTP according to the above point).
  • The development environment should be supported for RAD based IDE such as Eclipse Galileo.

I had few options like Hessian and Burlap. But these technologies are proprietary although they work well across firewalls. The Http invoker is the winner. The Http invoker is part of the Spring framework.

Note: Hessian and Burlap use proprietary serialization mechanisms which is portable to integrate with other technologies such as PHP and .NET. But Http Invoker support only Java serialization, this is the main disadvantage of using Http Invoker because its limited to use in the Java territories.

 
The Http Invoker is very similar to work with Hessian and Burlap in a developer perspective. Let us explore the use of Http invoker.
 

Design

One of my objective is RAD support. Eclipse has been chosen to develop this example. There are three projects has been created as shown in the following figure;
 
app_components
 
As shown in the above figure, HelloWeb and HelloClient both share the HelloShared subsystem.
  • SOSWeb is the web project which should be available in the Servlet container (in this example Servlet container is Apache Tomcat 6).
  • SOSClient is the client application which is spring based Java application.
  • SOSShared is the application which keeps shared items by both the above application. The main purpose of this application to avoid duplicate declarations.

 ClassStructure

I try to make the things simple as much as possible. In this class diagram, transfer objects and service interfaces are kept in the SOSShared subsystem because they are shared among Web and Client applications. For example, Child is a transfer object and HelloService is service interface which are available in the SOSShared subsystem. But service implementation is available in the SOSWeb subsystem and HelloClient in the SOSClient subsystem.

httpinvoker_SequenceDiagram

The objective of this hello world application is very simple to keep thing understandable. As shown in the above sequence diagram, frist HelloClient from the client side, send the request to HelloService via Http Invoker. In this request, newly created child will be sent to the SOSWeb subsystem, at the server side, this object will be save by the HelloServiceImpl. In the next, Client request, HelloClient requests the getHello() method from the HelloService, in return Http Invoker will execute th HelloServiceImpl and send bank the Child object to client side.

Implementation

Let’s go through the configuration first. Client side configration for HelloClient is as shown in the below code snippet.

................
................


	 
	 	http://localhost:8080/SOSWeb/hello.service
	 
	 
	 	org.sos.ss.hello.HelloService
	 

...
...

As shown in the above xml code, org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean is the proxy which will serialize the parameters and pass those serialized objects to the server side. The ugly code of “serviceUrl” can be replace by the place holder such as http://${serverName}/${contextPath}/hello.service, in which variable should be replaced by the property values. In this example, I will keep the above naked source to keep thing simple again.

The “serviceInterface” which should share the class from the SOSShare subsystem as explained above. In eclipse, you can make available by right click and selecting the “Build Path ->Configure Build Path” as shown in the following figure;

image In the Properties for SOSClient add the SOSShared by click and selecting it. Let’ go through the client source which is very typical Spring client, nothing to explain.

package org.sos.ss.client.hello;

import org.sos.ss.hello.HelloService;
import org.sos.ss.to.child.Child;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class HelloClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml"); 
		HelloService hello = (HelloService)ctx.getBean("helloservice");
		Child child = new Child();
		hello.setHello(child);
		Child c = hello.getHello();
		System.out.println("Name "+ c.getName()+ " Age: "+ c.getAge());

	}

}

As shown in the above code, first we create child and send it to the server by calling setHello() as depicted in the sequence diagram. The next server call is execution of getHello() that is 3rd step of the sequence diagram.

Next you have to deploy the HelloService in the server side. Eclipse Web dynamic project for Tomcat 6.0 is the project configuration for this example. There is configuration file hello-servlet.xml which is part of the Spring MVC framework. It should be named as hello-servlet.xml because “hello” is the value given for the servlet-mapping in the web.xml file given in the following code.

  ..............
  ..................
  SOSWeb
  
    index.html
    index.htm
    index.jsp
    default.html
    default.htm
    default.jsp
  
  
  	hello
  	org.springframework.web.servlet.DispatcherServlet
	1  
  
  
  
  	hello
  	*.service
  
  ...
  ...

In this example, Servlet mapping is "hello", therefore what ever the request received as <any name>.service should consult the hello handler configured in the hello-servlet.xml which is given in the following code snippet.

.................
.................


	


	org.sos.ss.hello.HelloService







	
		
			httpHelloService
		
	

...
...

The hello-servlet.xml define the  Service Interfaces and the Service implementations as shown in the following code.

...
...


	


	org.sos.ss.hello.HelloService







	
		
			httpHelloService
		
	

...
...

As shown in the above code, org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter handle the responsiblity of deserializtion of received objects, serialization of returns and method call translation as pure plain Java method calls. According to the above code, when request received as “hello.service”, that will be mapped to the httpHelloService using org.springframework.web.servlet.handler.SimpleUrlHandlerMapping. There can be number of mappings in the <props> although this example shows only one.

image

To thing works, you have to provide the SOSShared subsystem to the Apache Tomcat runtime as shown in the above figure, right click the application and select “Run As –> Run Configurations…”, then select the Tomcat runtime from the left hand side menu. You can add SOSShared to the “User Entries”.

The HelloServiceImpl is simple as following code snippet.

package org.sos.ss.hello;

import org.sos.ss.to.child.Child;

public class HelloServiceImpl implements HelloService {

	Child child;
	int i;
	@Override
	public Child getHello() {
		changeChild();
		return child;
	}

	@Override
	public void setHello(Child child) {
		this.child=child;

	}
	
	public void changeChild(){
		child.setName("Ojitha");
		child.setAge(i++);
	}

}

Now everything is ready to run, first you have to deploy SOSWeb to the Tomcat web server, and run the SOSClient as a typical Java application. In the output, for each execution of client application, age will be increased by one as shown in the above code.

The working source code of this example can be downloaded.  

Comments

Popular posts from this blog

How To: GitHub projects in Spring Tool Suite

Spring 3 Part 7: Spring with Databases

Parse the namespace based XML using Python