CPAN423 Enterprise Java Programming
Lecture #5: RMI with Servlets and JSP
Remote Method Invocation is one of the Java’s object-to-object based distributed computing technologies that allows Java objects running on separate processes to communicate with each other as if they where running in the same process. RMI was abased on technology called Remote Procedure Call. RPC allows a program to call a function from another program (can be on another computer) as if it was part of it. RPC perform all the networking and transmitting of data over the internet. Transmitting data is called datamarshalling. To work with RPC, you need to learn an Interface Definition Language to describe the functions that can be accessed remotely. RPC also does not support marshaling of objects.
When the object is register as a remote object, the client can obtain a remote reference to this object, and call methods of that object as if it was local object running in the same application.
RMI does all the marshalling of data and use object serialization mechanism to transfer Java objects. JSDK comes with a utility called rmic that generates all the networking code. To create a remote object, we need to perform the following steps:
- Define a remote interface that extends the interface java.rmi.Remote. Methods that the clients can invoke should be declared in this interface (no implementation). Each of these methods should throw exception of type java.rmi.RemoteException.
- Implement the remote interface by providing a class that extends java.rmi.server.UnicastRemoteObject and implements the remote interface. The constructor of UnicastRemoteObject class exports the remote object it can listen to remote requests. The constructor of any UnicastRemoteObject class must throw an exception of type java.rmi.RemoteException. The implementation class must define also a URI that the client can use to obtain a remote reference to the remote object. This URI identify the hostname and the port of the computer that the remote object will be registered. The format of this URI should be: rmi://host:port/remoteObjectname
The default port for RMI registry is 1099.The JSDK comes with a utility called rmiregistry used to manage the remote object registry.
The implementation class should also bind the remote object to the RMI registry with the defined URI using the static method java.rmi.Naming.rebind. If theremote object is already registered, the rebind method will register a new version of this object.
- Define the client application that will obtain a remote reference to the remote object. The client can be any Java-based application including Servlets, and JSP.
The client should use the static method java.rmi.Naming.lookup to obtain a remote reference to the remote object by providing the remote object’s URI.
- Compile and run the remote object and the client. The rmic utility is used to generate the stub class(s) that will be responsible for forwarding the method invocation to the RMI layer, which in turn handles the communication between the remote object and the client.
Java based application/applet runs in an environment called the sandbox where permission must be granted to the application in order to access system resources outside the sandbox. The permission should be declared in a file called security policy file and checked by the Security Manager class. The Security Manger class control what operations are permitted and it is one of the three components of security checking in Java. The other two components are the bytecode verifier and the class loader. The class loader is responsible for loading all the required class files to run a program into the java virtual machine and insure their integrity. The bytecode verifier inspect the loaded classes for illegal instructions like bad pointers, arrays out of boundary, variables are not initialized before they are used, and so on.
The JVM has a system wide security policy file called java.policy that grants specific permissions that affect the entire system. This file is located under jdk/jre/lib/security folder. JSDK comes with a utility called policytool used to edit the security policy file. Also you can use any editor to modify the security policy file manually. If the remote object has installed a SecurityManager, the proper security file must be provided.
Examples:
Ex1: RMI and servlet example:
In this example we will build a remote object that have a Servlet as a client. First we will build an interface called PersonalInterface. PersonalInterface.java should have the following content:
package ro;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface PersonalInterface extends Remote
{
boolean check(String name, String pass) throws RemoteException;
}
Then we will provide a class called PersonalInterfaceImlpl that provide implementation for the method check of interface PersonalInterface. This method will loop through two arrays of names and passwords to validate the user login. The user login(name/password) should be passed as parameters to check method. If a matching is found then check will return true, otherwise it will return false. PersonalInterfaceImpl.java should have the following content:
package ro;
import java.rmi.*;
import java.rmi.server.*;
public class PersonalInterfaceImpl extends UnicastRemoteObject implements PersonalInterface
{
/*
define two arrays for users’ names and passwords
*/
private String [] userName={"a","b","c"};
private String [] userPassword={"1","2","3"};
public PersonalInterfaceImpl () throws RemoteException
{
/*
call the super class constructor to export the remote object
*/
super();
}
/*
check for a match
*/
public boolean check(String name, String pass)
{
boolean found=false;
for (int i=0;i<userName.length;i++)
if (userName[i].equals(name) & userPassword[i].equals(pass))
found=true;
return found;
}
public static void main (String [] args)
{
if (System.getSecurityManager()==null)
{
System.setSecurityManager(new RMISecurityManager());
}
String serverName="rmi://localhost/PersonalInterface";
try
{
/*
bind the remote object to the URL rmi://localhost/PersonalInterface
*/
PersonalInterface pi=new PersonalInterfaceImpl();
Naming.rebind(serverName,pi);
System.out.println("Object is bounded");
}
catch(Exception e)
{
System.out.println(e.toString());}
}
}
Since we have installed a security manager with the RMI object, we have to provide a policy file that grants the required permission. Following is a policy file called java.policy that contain the required permission:
grant {
permission java.net.SocketPermission "*:1024-65535", "connect,accept";
permission java.net.SocketPermission "*:80", "connect";
};
The following is a Servlet called rimServlet that obtain a remote reference to the PersonalInterface object, and call check method to validate the user login.
import java.rmi.*;
import java.rmi.registry.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import ro.*;
public class rmiServlet extends HttpServlet
{
public void doPost (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
String uName=req.getParameter("userName");
String uPassword=req.getParameter("userPassword");
try
{
/*
obtain a remote reference to the remote object PersonalInterface
*/
PersonalInterface pi=(PersonalInterface) Naming.lookup("rmi://localhost:1099/PersonalInterface");
if (pi.check(uName,uPassword))
{
out.println("Login correct");
}
else
{
out.println("Login inccorrect <a href=' try again </a>");
}
}
catch(Exception e)
{
out.print( e.toString());
}
}
}
And here is an HTML file called loginUser.html that will be used to invoke the rmiServlet:
<html>
<title>Login Example</title>
</head>
<body>
<form method="post" action="
Enter User Name: <input type="text" name="userName" size="20" /<br>
Enter User password: <input type="password" name="userPassword" size="10" /<br>
<input type="submit" value="Login">
</form>
</html>
The following batch file shows the steps required to compile and run the remote object PersonalInerface.
set path=C:\Program Files\Java\jdk1.5.0_06\bin;
set classpath=.;
javac ro/*.java
rmic -v1.2 ro.PersonalInterfaceImpl
start rmiregistry
java -Djava.security.policy=ro/java.policy ro.PersonalInterfaceImpl
java -ro.PersonalInterfaceImpl
pause
The files PersonalInterface.java, PersonalInterfaceImpl.java, and java.policy should be stored under ro folder. The batch file should be stored one level above.
The servlet file (rimServlet.java) should be saved in the folder:
resin-x.x.x\webapps\cpan423\WEB-INF\Classes and the userLogin.html should be saved in the folder: resin-x.x.x\webapps\Cpan423.The following configuration should be added to the web.xml file:
<servlet>
<servlet-name>rmi</servlet-name>
<servlet-class>rmiServlet</servlet-class>
</servlet>
<servlet-mapping>
<url-pattern> /rmiServlet</url-pattern>
<servlet-name>rmi</servlet-name>
</servlet-mapping>
Also you have to copy the interface class(Personalinterface.class) and the stub class (PersonalInterfaceImpl_stub.class) to the folder in the folder:
resin-x.x.x\webapps\cpan423\WEB-INF\Classes
Ex2: RMI and JSP
In this example we will build a JSP called rmi.jsp that obtains a remote reference to PersonalInterface object. The procedure for compiling and running the remote object is the same as in Ex1. The JSP page should be saved in the folder in the folder: resin-x.x.x\webapps\cpan423
Remember that you need the interface class(Personalinterface.class) and the stub class (PersonalInterfaceImpl_stub.class) in the folder in the folder:
resin-x.x.x\webapps\cpan423\WEB-INF\Classes
Following is the source code for rmi.jsp:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"
<html xmlns="
<head>
<title>JSP Page</title>
</head>
<body>
<%@page import="java.rmi.* ,java.rmi.registry.*,ro.*" %>
<%
String uName=request.getParameter("userName");
String uPassword=request.getParameter("userPassword");
try
{
PersonalInterface pi=(PersonalInterface) Naming.lookup("rmi://localhost:1099/PersonalInterface");
if (pi.check(uName,uPassword))
{
out.println("Login correct");
}
else
{
out.println("Login inccorrect <a href=' try again </a>");
}
}
catch(Exception e)
{
out.println(e.toString());
}
%>
</body>
</html>
And here is an HTML file called loginUserJSP.html that will be used to invoke the rmi.jsp file:
<html>
<title>Login Example</title>
</head>
<body>
<form method="post" action="
Enter User Name: <input type="text" name="userName" size="20" /<br>
Enter User password: <input type="password" name="userPassword" size="10" /<br>
<input type="submit" value="Login">
</form>
</html>
The file loginUserJSP.html should be stored in the folder in the folder:
resin-x.x.x\webapps\cpan423
1