RMI – Client and run the Library

This is the last part in the build up to the RMI (Remote Method Invocation) this is the clients part, the previous part was the RMI library / server. Where the server will listen for a clients request.

So to start with we need to be able to call the remote server, so we need to be able to have permission from the RMI java security package.

System.setSecurityManager(new RMISecurityManager());

next we need to build up the RMI server request URL (where the server is and also the remote class that it is listening on and as taken from here we are listening on the “RemoteBook” class) (we are listening on the localhost as the server)

String remoteClass = "RemoteBook";
String rmiURL = "rmi://localhost/" + remoteClass;

since all the client needs to know is what interface has been implemented within the server (the borrowable interface) then we just need to create a new object based on that that then links to the servers listening class rmiURL (as taken from above)

Borrowable remoteBook = (Borrowable)Naming.lookup(rmiURL);

and then just call the functions that will have been implemented on the server (the server has used the Book.java which implements the Borrowable interface) because now they are linked.

The java Naming object is a RMI object that allows for the server to bind’s its class object to a URL and the client to link its interface object to the servers class object basically.

here is the client code in full

import java.util.*;
import java.rmi.*;
 
public class RMIClient {
	String remoteClass = "RemoteBook";
	String libraryCardNumber = "genuxCard";
 
	public RMIClient()
	{
		if (System.getSecurityManager()== null)
			System.setSecurityManager(new RMISecurityManager());
 
	}
 
	public boolean useLibrary()
	{
		boolean result = true;
		try {
			String rmiURL = "rmi://localhost/" + remoteClass;
			Borrowable remoteBook = (Borrowable)Naming.lookup(rmiURL);
			System.out.println("The book is checked out "+remoteBook.isCheckedOut());
 
			boolean outResult = remoteBook.checkOut(libraryCardNumber,new Date());
 
			if (outResult==true)
				System.out.println("Book checked out successfully");
			else
				result = false;
 
			if (remoteBook.isCheckedOut())
			{
				System.out.println("libraray Card number that has checked out the book is :"+remoteBook.checkedOutCardNumber());
			}
 
			boolean inResult = remoteBook.checkIn(libraryCardNumber, new Date());
 
			if (inResult==true)
				System.out.println("Book checked in");
			else
				result = false;
		}
		catch (Exception e)
		{
			System.out.println("RMI Error: "+e.getMessage());
			result = false;
		}
		return result;
	}
 
	public static void main(String[] args) {
		RMIClient RMIC = new RMIClient();
		boolean result = RMIC.useLibrary();
		if (result == false)
			System.out.println("Error using library");
 
	}
 
}

and if you save that as RMIClient.java, compile up the java files to create the class files

This is the policy file, if you save this as RMIpolicyfile.policy, it basically allows all permissions within the java security object, not the best security for servers but this will server as a local host test. (alter the where/your/class/files/are to where you are building up the java files into there class files, within eclipse it has a /src directory and a /bin so you would link to the /bin directory)

grant codeBase "file:/where/your/class/files/are" {
    permission java.security.AllPermission;
};

and now that you have the RMI server (RMIFactory) and the RMI client (RMIClient) all we need to do is to register the java RMI to allow connections on the linux command line I do

rmiregistry &

the “&” allows it to run in the back ground, then to run the server

java -Djava.security.policy=RMIpolicyfile.policy RMIFactory &
console output : Remote book object has been started

which this uses the security policy file from above and also runs again in the background (“&”) and now to just run the client

java -Djava.security.policy=RMIpolicyfile.policy RMIClient

once again since the client is requesting the RMI security, you need to tell it to use the RMI policy file from above, and the output would be

The book is checked out false
Book checked out successfully
libraray Card number that has checked out the book is :genuxCard Date taken out on Thu Apr 08 11:49:36 BST 2010
Book checked in

RMI – the Library factory

Now we have the library book, we can now build up the RMI library factory that will be the server for the clients to communicate to.

To start with we have to setup the security settings

System.setSecurityManager(new RMISecurityManager());

this is because the RMI library factory needs to “listen” on the server to remote clients to connect and due to the Java sandbox we have to make a request to the security manager to be allowed to “listen” for remote clients, without the permission there will be a error.

Remote error :Connection refused to host: 127.0.1.1; nested exception is: 
        java.net.ConnectException: Connection refused

I shall include the policy file when it comes to running the server/client setup.

now all we need to do is to bind the Book class RMI server and call it the “RemoteBook”, you need this to call with the client because you are basically allowing the server to communicate with the client to the Book that has been created (new Book(“Genuxs book… ) )

Book remoteBook = new Book("Genuxs book to borrow");
Naming.rebind("RemoteBook",remoteBook);

here is the full RMI Factory code

import java.rmi.*;
import java.rmi.server.*;
import java.net.*;
 
public class RMIFactory {
 
	public RMIFactory()
	{
		System.setSecurityManager(new RMISecurityManager());
	}
 
	public void createRemoteBook()
	{
		try {
			Book remoteBook = new Book("Genuxs book to borrow");
			Naming.rebind("RemoteBook",remoteBook);
 
		} 
		catch (RemoteException e)
		{
			System.out.println("Remote error :"+ e.getMessage());
		}
		catch (MalformedURLException mue)
		{
			System.out.println("Remote malformed error :"+mue.getMessage());
		}
 
		System.out.println("Remote book object has been started");
	}
 
	public static void main(String[] args) {
		RMIFactory RMIF = new RMIFactory();
		RMIF.createRemoteBook();
	}
 
}

if you save that as RMIFactory.java and next it is the client and running the RMI server and RMI client.

RMI – implementation of the library book

As from previous post, the Borrowable interface, for the RMI (Remote Method Invocation), this is the part of the Book class, this is what is called from the Library as such to see if a book has been taken out or not.

import java.util.*;
import java.rmi.*;
import java.rmi.server.*;
 
// UnicaseRemoteObject = remote object classes need to implement the related
// remote interface
public class Book extends UnicastRemoteObject implements Borrowable {
	private Date borrowDate;
	private Date returnDate;
	private String borrowerID;
	private String title;
	private boolean checkedOut = false;
 
	// create book.
	public Book (String bookName) throws RemoteException
	{
		title = bookName;
	}
 
	// is the book already checked out ?
	public boolean isCheckedOut() throws RemoteException
	{
		return checkedOut;
	}
 
	// if the book is checked out, return the library card number + date it was taken out on
	public String checkedOutCardNumber() throws RemoteException
	{
		String returnID = null;
		if (isCheckedOut())
		{
			returnID = borrowerID + " Date taken out on "+ borrowDate.toString();
		}
		return returnID;
	}
 
	public boolean checkOut(String cardNumber, Date d ) throws RemoteException
	{
		// do not check out the book if already checked out!
		if (isCheckedOut())
			return false;
		borrowerID = cardNumber;
		borrowDate = d;
		checkedOut = true;
		return true;
	}
 
	public boolean checkIn(String cardNumber, Date d) throws RemoteException
	{
		// if it is checked out, check the book in.
		if (isCheckedOut())
		{
			borrowerID = cardNumber;
			returnDate = d;
			checkedOut = false;
			return true;
		}
		return false;
	}
}

if you save that as Book.java, next comes the fun part the actual Library server as such.