Wednesday, July 22, 2009

Spring Remoting

Spring provides a special remoting strategy which allows for Java serialization via HTTP, supporting any Java interface. The corresponding support classes are HttpInvokerProxyFactoryBean and HttpInvokerServiceExporter.

I will write a simple service and a client to demonstrate the use of Spring HTTP Remoting. Let us follow the following steps -

1. Write an interface let say it is IMyTestService

package com.test.server;

public interface IMyTestService {
public int authenticateUser (String login, String password);
}

2. Write implementation implementing the above interface

package com.test.server;

public class MyTestService implements IMyTestService {

public int authenticateUser(String login, String password) {
System.out.println("MyTestService.authenticateUser called : " + login
+ " = " + password);
return 0;
}

}

3. Write applicationContext.xml to define the above mentioned service.

<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="myService" class="com.test.server.MyTestService" />
</beans>


4. Write web.xml

<?xml version="1.0" encoding="UTF-8" ?>
<web-app id="testwebapp" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Sample Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/myService</url-pattern>
</servlet-mapping>
</web-app>

So, here any request with url pattern /myService would be handled by servlet name "remoting". The servlet name "remoting" is mapped to servlet class org.springframework.web.servlet.DispatcherServlet

5. Now we will write servlet context configuration file. Since the servlet name is step 4 is given as "remoting" so we will write remoting-servlet.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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean name="/myService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="myService" />
<property name="serviceInterface" value="com.test.server.IMyTestService" />
</bean>
</beans>

We have just completed our simple service and all the required configuration files. Let us now deploy them before writing a sample client.

Copy the classes IMyTestService and MyTestService under WEB-INF/classes. We would require spring-2.5.4.jar and commons-logging.jar, copy them under WEB-INF/lib. Copy web.xml, applicationContext.xml and remoting-servlet.xml under WEB-INF

Restart tomcat and we are done.

Let us write a simple client now.

1. Write applicationContextClient.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

<bean id="myService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/test/myService" />
<property name="serviceInterface" value="com.test.server.IMyTestService" />
</bean>
</beans>

2. Write java class to test the service.

package com.test.client;

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

import com.test.server.IMyTestService;

public class MyTestClient {
public static void main (String [] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContextClient.xml");
IMyTestService testService = (IMyTestService) context.getBean("myService");
int result = testService.authenticateUser("Pranav", "123123");
System.out.println("testService.authenticateUser - " + result);
}
}

Isn't it so simple….