Wednesday, 16 June 2010

Ajax with Direct Web Remoting (DWR)

This is my blog entry after a long time.

Recently i have used ajax with dwr (Direct Web Remoting) and it was very useful. I would like to discuss the same this time.

DWR allows the us to call server-side Java objects from javascript with a great ease.

- Using DWR you can call server-side Java objects from javascript directly, so you can eliminate entire request-response handling code.

- DWR is deployed as a servlet within your Web application. But there is no need for you to write the servlet code to call the back end object.

- We can introduce the classes we require to call objects from. For each exposed class, DWR dynamically generates JavaScript to include in your Web page. The generated JavaScript contains stub functions that represent the corresponding methods on the Java class and also performs XMLHttpRequests behind the scenes. These requests are sent to the DWR servlet, which, in its second role, translates the request into a method call on a server-side Java object and sends the method's return value back to the client side in its servlet response, encoded into JavaScript.

- There are some utility functions provided to perform common UI tasks.


How to use it?

Ensure you have dwr.jar in your classpath.

Main components include:

- jsp event handler to call javascript.

- javascript function to call the server-side class.

- Server-side class to make the actual database call.

- dwr.xml file to expose the server-side class to the client.


Now let us look at an example.

In our jsp file, if you select a stream type, all the streams with that stream type should be populated dynamically.


<select id="streamType" name="streamType" onchange="onStreamTypeChange();">
<!-- options holding the list of stream types--!>
</select>

<select id="streamDesc" name="streamDesc">
<option value="">&nbsp;</option>
</select>


This calls the below javascript function to populate the relevant streams, whenever the value of this select list is changed (stream type is changed).


function onStreamTypeChange()

{

l = document.findJobs.streamType;

sST = l.options[l.selectedIndex].value;

StreamAdapter.getStreamsForStreamType(sST, populateStreams);

/*
StreamAdapter - JavaScriptName - specified in dwr.xml(explained below)
getStreamsForStreamType - methodName
sST - methodParams ...
populateStreams - callBack function
*/


}


This function passes the selected streamType into a method called getStreamsForStreamType of the object StreamAdapter.

After the remote method is called, the results from that method are passed to the popStreams javascript callback function(populateStreams).

- NOTE : callback function should be the last parameter. You can have multiple method params before that.


function populateStreams(data)

{

DWRUtil.removeAllOptions("streamDesc"); // Utility functions provided by DWR

DWRUtil.addOptions("streamDesc", data); // Utility functions provided by DWR

/*
if you want to access the elements inside the list,
then incoming list can be accessed as an array and
elements can be accessed as below...

streamDesc_1 = data[0];
streamDesc_2 = data[1];

*/


var l = document.findJobs.streamDesc;



for(i=0; i < l.options.length; i++)

{

if(l.options[i].value == "<c:out value="${sessionScope.findJobs.streamDesc}" />")

{

l.selectedIndex = i;

}

}

}


This method contains the logic to adjust the DOM to reflect the data coming back from the server-side. You will see there are a couple of DWR util functions in there to remove the current options from the select list and then add new options, which have come back from the server. The function then selects a value from the new select list based on a session attribute.

StreamAdapter is a server-side class that actually makes a database call. This class takes in the parameters sent from the JS function, calls down to a DAO class to get some results and returns a List back to the client side as below.


public class StreamAdapter
{

public List<String> getStreamsForStreamType(String streamType) throws Exception
{

CommonJobDAO dao = new CommonJobDAO();

List<String> result = dao.getStreamsForStreamType(streamType);

return result;
}

public List<StreamBean> "getStreamDetails(int stream_id){
....
}
}


In order to expose the StreamAdapter class to the client, there is a config file called dwr.xml. This file tells DWR to create a new instance of the StreamAdapter class whenever it is called and gives the location of the class as below.


<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">


<dwr>
<allow>
<create creator="new" javascript="StreamAdapter">
<param name="class" value="com.myproject.adapters.StreamAdapter"/>
<include method= "getStreamsForStreamType"/> <!OPTIONAL>
<include method= "getStreamDetails"/> <!OPTIONAL>
</create>
</allow>
<allow>
<create creator="new" javascript="AnotherAdapter">
<param name="class" value="com.myproject.adapter.FieldAdapter"/>
</create>
</allow>
</dwr>



The above is the simpler version of dwr.xml file.

if you are retrieving List or Map then you can use convert element which specifies the members to include in the JavaScript serialization of StreamBean.

You can declare the dwr servlet as below in web.xml file.


<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>


Pros and cons of DWR:

- Very easy to use.
- very quick.
- DWR does a great job of hiding the Ajax machinery, but it's important to remember that the network is not transparent .

Hope it will be useful.


References :
http://www.ibm.com/developerworks/java/library/j-ajax3/

Thursday, 21 May 2009

Method C : Delegate Struts Action management to the Spring framework

Here we are going to delegate Struts action management to the Spring framework.

All you have to do is...

For each action that uses Spring, you need to define the action mapping to use org.springframework.web.struts.DelegatingActionProxy and declare a matching (action "path" == bean "name") Spring bean for the actual Struts action. This is an example of an action that requires an instance of UserDatabase:

Note the changes in struts-config file.

Inside action-mappings instead of declaring the action's class name, it registers the name of Spring's proxy class. The DelegatingActionProxy class uses the action mapping name to look up the action in the Spring context. This is the context that was declared with ContextLoaderPlugIn.


<struts-config>
<form-beans>
<form-bean name="searchForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="id" type="java.lang.Long"/>
</form-bean>

</form-beans>

<global-forwards type="org.apache.struts.action.ActionForward">
<forward name="welcome" path="/welcome.do"/>
<forward name="searchEntry" path="/searchEntry.do"/>
<forward name="searchSubmit" path="/searchSubmit.do"/>
</global-forwards>

<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>

<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>

<action path="/searchSubmit"
type="org.springframework.web.struts.DelegatingActionProxy"
input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>

</action-mappings>

<message-resources parameter="ApplicationResources"/>

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>


<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>


</struts-config>



The corresponding Spring bean configuration...


<beans>

<bean id="employee_1" class="struts.spring.employee.beans.Employee">
<property name="id" value="1" />
<property name="name" value="Sneha" />
</bean>

<bean id="employee_2" class="struts.spring.employee.beans.Employee">
<property name="id" value="2" />
<property name="name" value="Prashant" />
</bean>

<bean id="employeeService" class="struts.spring.employee.business.EmployeeImpl">
<property name="employees">
<map>
<entry key="1">
<ref bean="employee_1" />
</entry>
<entry key="2">
<ref bean="employee_2" />
</entry>
</map>
</property>
</bean>

<bean name="/searchSubmit"
class="struts.spring.employee.actions.FindEmployeeAction">
<property name="employeeService">
<ref bean="employeeService"/>
</property>
</bean>

</beans>



Merits:
1. As the action is under Spring's control, it populates the action's JavaBean properties and leaves the door open to applying features such as Spring's AOP interceptors.


The action-delegation solution is the best of the three.

Hope it will be useful...

References : http://www.ibm.com/developerworks/java/library/j-sr2.html

Method B : Override the Struts RequestProcessor with Spring's DelegatingRequestProcessor

To avoid the above disadvantage of coupling the Struts Action to the Spring framework, you can override the Struts RequestProcessor processor with the org.springframework.web.struts.DelegatingRequestProcessor class.

To do the above just use tag to override the default Struts RequestProcessor with the DelegatingRequestProcessor in Struts-config file. Then register the action in Spring config file where you register other beans.


<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
<form-beans>
<form-bean name="searchForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="id" type="java.lang.Long"/>
</form-bean>

</form-beans>

<global-forwards type="org.apache.struts.action.ActionForward">
<forward name="welcome" path="/welcome.do"/>
<forward name="searchEntry" path="/searchEntry.do"/>
<forward name="searchSubmit" path="/searchSubmit.do"/>
</global-forwards>

<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>

<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>

<action path="/searchSubmit"
type="struts.spring.employee.actions.FindEmployeeAction"
input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>

</action-mappings>

<message-resources parameter="ApplicationResources"/>

<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>


<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>


</struts-config>



and here is Spring config file. Register the action here and remember name attribute to match the struts-config action mapping name.
employeeService property will be populated at runtime using getter injection.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="employee_1" class="struts.spring.employee.beans.Employee">
<property name="id" value="1" />
<property name="name" value="Sneha" />
</bean>

<bean id="employee_2" class="struts.spring.employee.beans.Employee">
<property name="id" value="2" />
<property name="name" value="Prashant" />
</bean>

<bean id="employeeService" class="struts.spring.employee.business.EmployeeImpl">
<property name="employees">
<map>
<entry key="1">
<ref bean="employee_1" />
</entry>
<entry key="2">
<ref bean="employee_2" />
</entry>
</map>
</property>
</bean>

<bean name="/searchSubmit"
class="struts.spring.employee.actions.FindEmployeeAction">
<property name="employeeService">
<ref bean="employeeService"/>
</property>
</bean>

</beans>



Now your action class extend the Struts's org.apache.struts.action.Action Class instead of Spring ActionSupport Class.


public class FindEmployeeAction extends Action{

private EmployeeI employeeService;

public EmployeeI getEmployeeService() {
return employeeService;
}

public void setEmployeeService(EmployeeI employeeService) { //1
this.employeeService = employeeService;
}

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

DynaActionForm searchForm = (DynaActionForm) form;
Long id = Long.parseLong(searchForm.get("id").toString());

System.out.println("Inside FindEmployeeAction_2 id = "+id);

Employee employee = getEmployeeService().findEmployeeById(id);

if (null == employee) {
System.out.println("employee not found");
return mapping.findForward("failure") ;
}

System.out.println("employee found");
request.setAttribute("emp", employee);
return mapping.findForward("success");
}
}



As you have seen at 1 employeeService JavaBean property will be automatically populated by the DelegatingRequestProcessor.

Merits:
1. Protects the Struts action from knowing it's being managed by Spring while giving you all the benefits of Spring's action management framework.
2. Because your Struts actions are oblivious to the existence of Spring, you can swap out Spring for some other inversion of control container without refactoring your Struts code.
3. This approach is definitely better than the first one

Demerits:
1. If you were using a different RequestProcessor, then you would need to integrate the Spring DelegatingRequestProcessor manually.
2. The added code would become a maintenance hassle and would also reduce your application's flexibility going forward. Moreover, there has been some talk of replacing the Struts RequestProcessor with a chain of command. Such a change would negatively impact the longevity of this solution.

Hope it will be useful...

References : http://www.ibm.com/developerworks/java/library/j-sr2.html

Method A : Using Spring's ActionSupport Class to integrate Struts

Here we are going to use Spring's ActionSupport class to integrate Struts.

Action classes of Struts framework do not get started as Spring framework beans, thus cannot be wired through Dependency Injection

If the Action class wants to access beans of Spring framework, it has to access them manually.

Instead of extending Action class, you can extend Spring's org.springframework.web.struts.ActionSupport Class which provides getWebApplicationContext() method to obtain a Spring context

Action Support provides a reference to the current Spring application context, e.g. for bean lookup or resource loading
- Auto-detects a ContextLoaderPlugIn context, falling back to the root WebApplicationContext.
- For typical usage, i.e. accessing middle tier beans, use a root WebApplicationContext.

Below is how your Struts Action Class look like :


public class FindEmployeeAction extends ActionSupport{ //1
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

DynaActionForm searchForm = (DynaActionForm) form;
Long id = Long.parseLong(searchForm.get("id").toString());

System.out.println("Inside FindEmployeeAction id = "+id);

ApplicationContext ctx = getWebApplicationContext(); //2
EmployeeI employeeService = (EmployeeI) ctx.getBean("employeeService"); //3

Employee employee = employeeService.findEmployeeById(id);

if (null == employee) {
return mapping.findForward("failure") ;
}

request.setAttribute("emp", employee);
return mapping.findForward("success");
}
}



Let see how the above Action Class is different from Traditional Action Class and how can it provide a reference to the current Spring context.

1. Extend ActionSupport(org.springframework.web.struts.ActionSupport) Class instead Action Class.
2. ApplicationContext refernce is obtained through getWebApplicationContext() method which is there in ActionSupport Class.
3. Look up for Spring bean using the context reference you have obtained.

Have a look at Spring-config file also.


<beans>

<bean id="employee_1" class="struts.spring.employee.beans.Employee">
<property name="id" value="1" />
<property name="name" value="Sneha" />
</bean>

<bean id="employee_2" class="struts.spring.employee.beans.Employee">
<property name="id" value="2" />
<property name="name" value="Prashant" />
</bean>

<bean id="employeeService" class="struts.spring.employee.business.EmployeeImpl">
<property name="employees">
<map>
<entry key="1">
<ref bean="employee_1" />
</entry>
<entry key="2">
<ref bean="employee_2" />
</entry>
</map>
</property>
</bean>


</beans>



Merits :
1. Very Simple and easy to understand.

Demerits:
1. It couples the Struts action to the Spring framework. If you ever decide to replace Spring, you would have to rewrite the code.
2. As the Struts action isn't under Spring's control, it can't reap the benefits of Spring AOP.
3. Useful when using multiple independent Spring contexts, but for the most part it's not as desirable a solution as the other two choices.


Hope it will be useful...

References : http://www.ibm.com/developerworks/java/library/j-sr2.html

Wednesday, 20 May 2009

Integrating Spring with Struts

Key to the Spring Framework is the freedom to choose what works best for your application. Spring offers you choices when building web applications, too. Although Spring offers its own very capable web framework, you are free to choose another if you’d like and still be able to take advantage of Spring in the other layers of your application.

Advantages of integrating a Struts application into the Spring framework:

1. Spring was explicitly designed to resolve some of the real-world problems of JEE, such as complexity, poor performance, testability, and much more.
2. Second, the Spring framework includes an AOP implementation that lets you apply aspect-oriented techniques to normal object-oriented code.

Both Struts and Spring frameworks have their merits and drawbacks, but most would agree that Struts is still king when it comes to MVC. Many development teams have learned to rely on Struts as the foundation for building quality software under strict deadlines. With so much momentum behind Struts, even development teams that would like to integrate features of the Spring framework don't want to switch to Spring MVC. The good news is that you don't have to. The Spring architecture allows you to connect Struts as your Web framework to Spring-based business and persistence layers.

Below we will see three approaches to integrating Struts applications into the Spring framework and discuss their merits and demerits.

A. Using Spring's ActionSupport class to integrate Struts.
B. Override the Struts RequestProcessor with Spring's DelegatingRequestProcessor.
C. Delegate Struts Action management to the Spring framework.

Whatever technique you use, you will need to add the Spring ContextLoaderPlugin to load the Spring application context for the Struts ActionServlet. Simply add the plug-in to your struts-config.xml file as you would any other plug-in, as shown below:


<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>



and here is the code for my bean, interface and impl which is common to all three methodologies.


public class Employee implements Serializable{

private Long id;
private String name;

public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}

public interface EmployeeI {

public Employee findEmployeeById(Long id);

public int getNoOfEmployees();
}

public class EmployeeImpl implements EmployeeI{

private Map<Long,Employee> employees = new HashMap<Long,Employee>();

public Employee findEmployeeById(Long id){
System.out.println("Inside findEmployeeById id = "+id);
Employee employee = (Employee)employees.get(id.toString());
System.out.println("Employee found = "+employee);
return employee;
}

public int getNoOfEmployees(){
return employees.size();
}

public Map<Long, Employee> getEmployees() {
return employees;
}

public void setEmployees(Map<Long, Employee> employees) {
this.employees = employees;
}

}


In my Impl Class I am having HashMap which is set at runtime using Spring's getter injection.

I have divided three methodologies into three ariticles as dont want to make it messy. Complete code is provided in the respective articles.

Method A : A. Using Spring's ActionSupport class to integrate Struts.

Method B : B. Override the Struts RequestProcessor with Spring's DelegatingRequestProcessor.

Method C : C. Delegate Struts Action management to the Spring framework.

If you directly want to go the best method. Find out my continuation article,
C. Delegate Struts Action management to the Spring framework.

Thursday, 14 May 2009

RMI using Spring

Let us look at Spring’s support to Remoting.

Spring supports remoting for several different Remote Procedure Call models, including Remote Method Invocation (RMI), Caucho’s Hessian and Burlap, and Spring’s own HTTP invoker.

Spring offers a POJO-based programming model for both your server and client, no matter which remoting solution you choose. This is accomplished using a proxy factory bean that enables you to wire remote services into properties of your other beans as if they were local objects.

The client makes calls to the proxy as if the proxy were providing the service functionality. The proxy communicates with the remote service on behalf of the client. It handles the details of connecting and making remote calls to the remote service.

If the call to the remote service results in a java.rmi.RemoteException, the proxy handles that exception and rethrows it as an unchecked
org.springframework.remoting.RemoteAccessException. Remote exceptions usually signal problems such as network or configuration issues that can’t be gracefully recovered from. Since there’s usually very little that a client can do to gracefully recover from a remote exception, rethrowing a RemoteAccessException makes it optional for the client to handle the exception.

Spring simplifies the RMI model by providing a proxy factory bean that enables you to wire RMI services into your Spring application is if they were local JavaBeans. Spring also provides a remote exporter that makes short work of converting your Spring-managed beans into RMI services.

Spring’s RmiProxyFactoryBean is a factory bean that creates a proxy to an RMI service. RmiProxyFactoryBean produces a proxy object that talks to remote RMI services on behalf of the client. The client talks to the proxy through the service’s interface as if the remote service were just a local POJO.

RmiProxyFactoryBean certainly simplifies the use of RMI services in a Spring application. But that’s only half of an RMI conversation.

Spring provides an easier way to publish RMI services. Instead of writing RMI-specific classes with methods that throw RemoteException, you simply write a POJO that performs the functionality of your service. Spring handles the rest.

For a typical Spring Application we need the following files:

1. An interface that defines the functions.

2. An Implementation that contains properties, its setter and getter methods, functions etc.

3. A XML file called Spring configuration file.

4. Client program that uses the function

Because the service interface doesn’t extend java.rmi.Remote and none of its methods throw java.rmi.RemoteException, this trims the interface down a bit. But more importantly, a client accessing the service through this interface will not have to catch exceptions that they probably won’t be able to deal with. Instead of generating a server skeleton and client stub using rmic and manually adding it to the RMI registry (as you would in conventional RMI), we’ll use Spring’s RmiServiceExporter.

RmiServiceExporter exports any Spring-managed bean as an RMI service. RmiServiceExporter works by wrapping the bean in an adapter class. The adapter class is then bound to the RMI registry and proxies requests to the service class.

The simplest way to use RmiServiceExporter to expose the employeeService bean as an RMI service is to configure it in Spring with the following XML:


<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="employee-service"/>
<property name="service" ref="employeeService"/>
<property name="serviceInterface" value="rmi.common.EmployeeI"/>
<property name="registryPort" value="1234"/>
</bean>



Here the employeeService bean is wired into the service property to indicate that RmiServiceExporter is going to export the bean as an RMI service. ServiceName property names the RMI service and the serviceInterface property specifies the interface implemented by the service.


<bean id="employeeService" class="rmi.server.EmployeeImpl">
</bean>


Now let us look at an example...

Let us have simple employee recruitment service exposed through EmployeeI interface which contains methods to add, remove and get number of employees.


public class Employee implements Serializable {
private String name;
private String address;

public Employee(String name,String address){
this.name = name;
this.address = address;
}

// getters and setters
}


public interface EmployeeI {

public void addEmployee(Employee employee);

public void removeEmployee(Employee employee);

public List<Employee> getEmployees();

}



Here is the implementation for EmployeeI interface.


public class EmployeeImpl implements EmployeeI{

private List<Employee> employees = new ArrayList<Employee>();

public void addEmployee(Employee employee) {
employees.add(employee);
}

public void removeEmployee(Employee employee){
employees.remove(employee);
}

public List<Employee> getEmployees() {
return employees;
}
}



On the server side, we need to configure Spring to export the service through RMI. As we discussed earlier we can do it by RmiServiceExporter.
The interface can be accessed by using RmiProxyFactoryBean, or via plain RMI in case of a traditional RMI service. The RmiServiceExporter explicitly supports the exposing of any non-RMI services via RMI invokers. Of course, we first have to set up our service in the Spring container:


<beans>
<bean id="employeeService" class="rmi.server.EmployeeImpl"/>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="employee-service"/>
<property name="service" ref="employeeService"/>
<property name="serviceInterface" value="rmi.common.EmployeeI"/>
<property name="registryPort" value="1234"/>
</bean>
</beans>



Now to run the server side service you need Spring context initialization.


public class EmpServerDemo {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("rmi/server/rmi-server-context.xml");
}
}


Now let us have a look at client side.

To link in the service on the client, we'll create a separate Spring container, containing the simple object and the service linking configuration bits:


<beans>
<bean id="employeeService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1234/employee-service"/>
<property name="serviceInterface" value="rmi.common.EmployeeI"/>
</bean>
</beans>



You can make client calls through the below code...


public class EmpClientDemo {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("rmi/client/rmi-client-context.xml");
EmployeeI employee = (EmployeeI) ctx.getBean("employeeService");
employee.addEmployee(new Employee("Prashant", "address1"));
employee.addEmployee(new Employee("Sneha", "address2"));
List<Employee> employees = employee.getEmployees();
System.out.println("Total number of employees: " + employees.size());
Iterator<Employee> it = employees.iterator();
while (it.hasNext()) {
Employee emp = (Employee) it.next();
System.out.println(" " + emp);
}
}
}



Therefore, the client will not be aware of the fact that the service is running remote and even less about the fact that its method calls are marshaled through RMI. The Spring bean configuration file takes care of these details, so the client code will not be affected if we change the remoting strategy or even if we choose to run the service in-process.

First run the EmpServerDemo in one console to launch the RMI server and then run the EmpClientDemo in another console.

RMI with Spring is as simple as that.

Hope it will be useful....

References :

Spring in Action by Craig Walls.

http://cosminaru.ro/blog/2006/11/02/spring-by-examples-rmi/.