Remote Method Invocation (RMI) Model:
RMI was first introduced in JDK 1.1. But developing and accessing RMI services involves various steps and also have lookups which makes the code hard to test. Spring simplifies the RMI by providing a 'proxy factory bean' that enables us to wire the RMI services into spring application as if they were local beans. Spring also provides a remote exporter that converts our 'spring managed beans' into RMI services.
Spring's 'RmiProxyFactoryBean' is a factory bean that creates a proxy to RMI service. It is declared spring configuration file under the <bean> tag as follows,
<bean id="service1"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl">
<value>rmi://${hostname}/service1</value>
</property>
<property name="serviceInterface">
<value>service1</value>
</property>
</bean>
The url of the RMI service is set through the 'serviceUrl' property. The 'serviceInterface' property specifies the interface that the service implements and only through that the client invokes methods on the service.
For using the service the implementation code is wired to the RMI using the following code,
<bean id="serviceimpl" class="serviceimpl">
<property name="service1">
<ref bean="service1"/>
</property>
</bean>
-------------------------------------------
First set the path and classpath as before. Next edit the RMI service.
//f:\springdemo\rmserver.java
import java.rmi.*;
public interface rmserver extends Remote
{
String getresult(String s) throws RemoteException;
}
----------------------------------------------
//f:\springdemo\rmserverimpl.java
import java.rmi.*;
import java.rmi.server.*;
public class rmserverimpl extends UnicastRemoteObject
implements rmserver
{
public static void main(String args[])
{
try
{
rmserverimpl ob = new rmserverimpl();
Naming.rebind("rmserver",ob);
System.out.println("ready");
}
catch(Exception e1)
{System.out.println(""+e1);}
}
public rmserverimpl() throws RemoteException
{
System.out.println("constructor ok");
}
public String getresult(String a) throws RemoteException
{
return "Hai..."+a;
}
}
----------------------------------------------
//f:\springdemo\rmserver.xml
<?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="rmserver"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl">
<value>rmi://localhost/rmserver</value>
</property>
<property name="serviceInterface">
<value>rmserver</value>
</property>
</bean>
<bean id="rmserverimpl" class="rmserverimpl">
<property name="rmserver">
<ref bean="rmserver"/>
</property>
</bean>
</beans>
---------------------------------------------
//f:\springdemo\rmspring.java
import java.rmi.*;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.xml.*;
import org.springframework.core.io.*;
public class rmspring
{
public static void main(String args[])
{
try
{
System.out.println("Wait..");
Resource res = new ClassPathResource("rmi.xml");
BeanFactory factory = new XmlBeanFactory(res);
rmserver bean1 = (rmserver) factory.getBean("rmserver");
String r=bean1.getresult(args[0]);
System.out.println(r);
}
catch(Exception e1)
{System.out.println(""+e1);}
}
}
---------------------------------------
To run:
f:\springdemo>javac rmserver.java
f:\springdemo>javac rmserverimpl.java
f:\springdemo>rmic rmserverimpl (To create stub and skeleton)
f:\springdemo>javac rmspring.java
f:\springdemo>start rmiregistry (a blank window will appear)
f:\springdemo>java rmserverimpl
Open another Window and run the client code by giving the argument
f:\springdemo>java rmspring "sam"
We will get the output as:
Wait..
......
Hai... sam
Here we have removed the 'lookup' code in the client side.
-----------------------------------------------------------------
Spring also supports the server side of RMI. Here the service itself is written with spring and it is exposed as an RMI service. Here the bean is written as a simple JavaBean. Also we need not generate the stub and skeleton using 'rmic' command and manually add it to RMI registry. Instead of these traditional procedure 'RmiServiceExporter' is used to export any Spring managed bean as an RMI service. It wrapps the bean in an adapter class. The adapter class is then bound to RMI registry and the proxies request the service.
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="service1">
<ref bean="service1"/>
</property>
<property name="serviceName">
<value>service1</value>
</property>
<property name="serviceInterface">
<value>service1</value>
</property>
</bean>
The 'serviceName property' indicates the name of service and 'serviceInterface' specifies the interface implemented by the service. There is no need of 'serviceUrl' here
First set the path and classpath as before. Next edit the service.
//f:\springdemo\rmservice.java
public interface rmservice
{
String getresult(String s);
}
------------------------------------------
//f:\springdemo\rmserviceimpl.java
public class rmserviceimpl implements rmservice
{
public static void main(String args[])
{
System.out.println("ready");
}
public rmserviceimpl()
{
System.out.println("constructor ok");
}
public String getresult(String a)
{
return "Hai"+a;
}
}
------------------------------------------
//f:\springdemo\rmservice.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/ spring-beans.dtd">
<beans>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="service">
<value>rmservice</value>
</property>
<property name="serviceName">
<value>service1</value>
</property>
<property name="serviceInterface">
<value>rmservice</value>
</property>
</bean>
<bean id="rmservice" class="rmserviceimpl">
</bean>
</beans>
------------------------------------------
//f:\springdemo\rmserviceclient.java
import java.io.*;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.xml.*;
import org.springframework.core.io.*;
class rmserviceclient
{
public static void main(String args[])
{
try
{
System.out.println("Wait..");
Resource res = new ClassPathResource("rmservice.xml");
BeanFactory factory = new XmlBeanFactory(res);
System.out.println("factory created");
rmservice bean1 = (rmservice)factory.getBean("rmservice");
String s = bean1.getresult(args[0]);
System.out.println(s);
}
catch(Exception e1)
{System.out.println(""+e1);}
}
}
---------------------------------------
To run:
f:\springdemo>javac rmservice.java
f:\springdemo>javac rmserviceimpl.java
f:\springdemo>javac rmserviceclient.java
f:\springdemo>java rmsserviceclient
We will get Output as:
Wait..
Aug 12, 2002 10:55:07 PM
org.springframework.beans.factory.
xml.XmlBeanDefinitionReader
loadBeanDefinitions
INFO: Loading XML bean definitions from
class path resource[rmservice.xml]
Aug 12, 2002 10:55:07 PM
org.springframework.beans.factory.
support.AbstractBeanFactory getBean
INFO: Creating shared instance of
singleton bean 'rmservice'
constructor ok
Hai...sam
Here the service interface doesn't extend the 'java.rmi.Remote' method and 'RemoteException' is not thrown by the methods. There is no binding in the implementation code. Also we can direcly run the client. No run to run 'rmserverimpl' first. Also there is no need to run the RMI registry.
RMI was first introduced in JDK 1.1. But developing and accessing RMI services involves various steps and also have lookups which makes the code hard to test. Spring simplifies the RMI by providing a 'proxy factory bean' that enables us to wire the RMI services into spring application as if they were local beans. Spring also provides a remote exporter that converts our 'spring managed beans' into RMI services.
Spring's 'RmiProxyFactoryBean' is a factory bean that creates a proxy to RMI service. It is declared spring configuration file under the <bean> tag as follows,
<bean id="service1"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl">
<value>rmi://${hostname}/service1</value>
</property>
<property name="serviceInterface">
<value>service1</value>
</property>
</bean>
The url of the RMI service is set through the 'serviceUrl' property. The 'serviceInterface' property specifies the interface that the service implements and only through that the client invokes methods on the service.
For using the service the implementation code is wired to the RMI using the following code,
<bean id="serviceimpl" class="serviceimpl">
<property name="service1">
<ref bean="service1"/>
</property>
</bean>
-------------------------------------------
First set the path and classpath as before. Next edit the RMI service.
//f:\springdemo\rmserver.java
import java.rmi.*;
public interface rmserver extends Remote
{
String getresult(String s) throws RemoteException;
}
----------------------------------------------
//f:\springdemo\rmserverimpl.java
import java.rmi.*;
import java.rmi.server.*;
public class rmserverimpl extends UnicastRemoteObject
implements rmserver
{
public static void main(String args[])
{
try
{
rmserverimpl ob = new rmserverimpl();
Naming.rebind("rmserver",ob);
System.out.println("ready");
}
catch(Exception e1)
{System.out.println(""+e1);}
}
public rmserverimpl() throws RemoteException
{
System.out.println("constructor ok");
}
public String getresult(String a) throws RemoteException
{
return "Hai..."+a;
}
}
----------------------------------------------
//f:\springdemo\rmserver.xml
<?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="rmserver"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl">
<value>rmi://localhost/rmserver</value>
</property>
<property name="serviceInterface">
<value>rmserver</value>
</property>
</bean>
<bean id="rmserverimpl" class="rmserverimpl">
<property name="rmserver">
<ref bean="rmserver"/>
</property>
</bean>
</beans>
---------------------------------------------
//f:\springdemo\rmspring.java
import java.rmi.*;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.xml.*;
import org.springframework.core.io.*;
public class rmspring
{
public static void main(String args[])
{
try
{
System.out.println("Wait..");
Resource res = new ClassPathResource("rmi.xml");
BeanFactory factory = new XmlBeanFactory(res);
rmserver bean1 = (rmserver) factory.getBean("rmserver");
String r=bean1.getresult(args[0]);
System.out.println(r);
}
catch(Exception e1)
{System.out.println(""+e1);}
}
}
---------------------------------------
To run:
f:\springdemo>javac rmserver.java
f:\springdemo>javac rmserverimpl.java
f:\springdemo>rmic rmserverimpl (To create stub and skeleton)
f:\springdemo>javac rmspring.java
f:\springdemo>start rmiregistry (a blank window will appear)
f:\springdemo>java rmserverimpl
Open another Window and run the client code by giving the argument
f:\springdemo>java rmspring "sam"
We will get the output as:
Wait..
......
Hai... sam
Here we have removed the 'lookup' code in the client side.
-----------------------------------------------------------------
Spring also supports the server side of RMI. Here the service itself is written with spring and it is exposed as an RMI service. Here the bean is written as a simple JavaBean. Also we need not generate the stub and skeleton using 'rmic' command and manually add it to RMI registry. Instead of these traditional procedure 'RmiServiceExporter' is used to export any Spring managed bean as an RMI service. It wrapps the bean in an adapter class. The adapter class is then bound to RMI registry and the proxies request the service.
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="service1">
<ref bean="service1"/>
</property>
<property name="serviceName">
<value>service1</value>
</property>
<property name="serviceInterface">
<value>service1</value>
</property>
</bean>
The 'serviceName property' indicates the name of service and 'serviceInterface' specifies the interface implemented by the service. There is no need of 'serviceUrl' here
First set the path and classpath as before. Next edit the service.
//f:\springdemo\rmservice.java
public interface rmservice
{
String getresult(String s);
}
------------------------------------------
//f:\springdemo\rmserviceimpl.java
public class rmserviceimpl implements rmservice
{
public static void main(String args[])
{
System.out.println("ready");
}
public rmserviceimpl()
{
System.out.println("constructor ok");
}
public String getresult(String a)
{
return "Hai"+a;
}
}
------------------------------------------
//f:\springdemo\rmservice.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/ spring-beans.dtd">
<beans>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="service">
<value>rmservice</value>
</property>
<property name="serviceName">
<value>service1</value>
</property>
<property name="serviceInterface">
<value>rmservice</value>
</property>
</bean>
<bean id="rmservice" class="rmserviceimpl">
</bean>
</beans>
------------------------------------------
//f:\springdemo\rmserviceclient.java
import java.io.*;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.xml.*;
import org.springframework.core.io.*;
class rmserviceclient
{
public static void main(String args[])
{
try
{
System.out.println("Wait..");
Resource res = new ClassPathResource("rmservice.xml");
BeanFactory factory = new XmlBeanFactory(res);
System.out.println("factory created");
rmservice bean1 = (rmservice)factory.getBean("rmservice");
String s = bean1.getresult(args[0]);
System.out.println(s);
}
catch(Exception e1)
{System.out.println(""+e1);}
}
}
---------------------------------------
To run:
f:\springdemo>javac rmservice.java
f:\springdemo>javac rmserviceimpl.java
f:\springdemo>javac rmserviceclient.java
f:\springdemo>java rmsserviceclient
We will get Output as:
Wait..
Aug 12, 2002 10:55:07 PM
org.springframework.beans.factory.
xml.XmlBeanDefinitionReader
loadBeanDefinitions
INFO: Loading XML bean definitions from
class path resource[rmservice.xml]
Aug 12, 2002 10:55:07 PM
org.springframework.beans.factory.
support.AbstractBeanFactory getBean
INFO: Creating shared instance of
singleton bean 'rmservice'
constructor ok
Hai...sam
Here the service interface doesn't extend the 'java.rmi.Remote' method and 'RemoteException' is not thrown by the methods. There is no binding in the implementation code. Also we can direcly run the client. No run to run 'rmserverimpl' first. Also there is no need to run the RMI registry.