You are on page 1of 4

Lab5 - Exercise 3

Mauro Conti Eyüp S. Canlar

17 November 2011

1 Introduction
In this document we will start with a brief set of reminders about RMI (Section 2). Then we will provide a
working toy example (Section 3). So, you can get acquainted with programming, compiling, and running
RMI programs. Finally, we explain what you have to do for Exercise 3 (Section 4). We advice the
students to follow this document. However, if you are confident about your programming skills, then you
can skip sections 1 and 2.

2 Reminders on RMI
Java Remote Method Invocation (RMI) enables the programmer to write distributed Java programs. In
particular, RMI makes it possible for Java programs to invoke methods of (remote) objects that possibly
reside on a different (remote) computer.
The architecture that makes RMI possible consists of three parties: (i) a client, (ii) a server, and (iii)
a naming service (rmiregistry). The client is the process that invokes a method on a remote object.
In contrast, the server is the process that owns the remote object. This remote object is just another
ordinary object in the address space of the server. Finally, the rmiregistry is a name server that has
a table that maps objects to remote references. To clarify, servers that want to provide RMI services
register their remote objects at the rmiregistry. In addition, clients that look for a specific remote
object can contact the rmiregistry to get a remote reference for the required remote object.
We also have to remind you about several things related to the rmiregistry.

• Each machine that hosts remote Objects needs to have a rmiregistry name server running.

• It is started up by giving the following command at a Linux shell:

– rmiregistry <port>
– If you do not specify a port number, then it will make use of port 1099 by default.

Finally, you should also remember that in RMI, by default the parameters are passed by value. If you
do not take this into account you can cause huge data transfers. To clarify this, consider the following.
Let us assume we give a remotely invoked method, the head of a LinkedList that contains database entries
as a parameter. In this case, the whole list and all the data that each node in the list refers to are passed
to the server.

3 A Toy Example: Calculator


Before we give you the details of the toy example we will first tell you which files you have to implement
for a minimal RMI client/server program. So, to write a minimal RMI client/server program you need
to write the following.

• An interface for the remote object: Remote.java

• An implementation of the remote object: RemoteImpl.java

• A server that will run the remote object: RemoteServer.java

• A client to access the server: RemoteClient.java

1
Now we know what we have to write, we can continue with our example. In this example we will
write a calculator RMI client/server program. The first thing that we want to write is the interface
of the calculator. In our case the calculator can only perform additions and subtractions. So, the
Calculator.java interface is specified as follows:
1 public i n t e r f a c e C a l c u l a t o r extends j a v a . rmi . Remote {
2 public long add ( long a , long b )
3 throws j a v a . rmi . RemoteException ;
4
5 public long sub ( long a , long b )
6 throws j a v a . rmi . RemoteException ;
7 }

The interface has to adhere to the following rules:


• The interface must extend java.rmi.Remote
• All methods specified in the interface must throw the java.rmi.RemoteException exception
You can compile this by giving the following command at a Linux shell.
1 $ javac Calculator . java

Now that we have the interface we can write the implementation of the remote object as follows.
1 public c l a s s C a l c u l a t o r I m p l extends
2 j a v a . rmi . s e r v e r . UnicastRemoteObject
3 implements C a l c u l a t o r {
4
5 // I m p l e m e n t a t i o n s must have
6 // an e x p l i c i t c o n s t r u c t o r
7 public C a l c u l a t o r I m p l ( )
8 throws j a v a . rmi . RemoteException {
9 super ( ) ;
10 }
11
12 public long add ( long a , long b )
13 throws j a v a . rmi . RemoteException {
14 return a + b ;
15 }
16
17 public long sub ( long a , long b )
18 throws j a v a . rmi . RemoteException {
19 return a − b ;
20 }
21 }

The implementation of the remote objects also have to adhere to some rules:
• It must implement the interface for the remote object
• It must inherit from the java.rmi.server.UnicastRemoteObject class
• It must have an explicit constructor which throws the java.rmi.RemoteException exception
We can compile the code for the implementation of the remote object by giving the following command
at a Linux shell:
1 $ javac CalculatorImpl . java

The next item on the list of files that we have to implement is the server that will run the remote
object. In our toy example this remote server is implemented as follows:
1 import j a v a . rmi . Naming ;
2
3 public c l a s s C a l c u l a t o r S e r v e r {
4
5 public C a l c u l a t o r S e r v e r ( ) {
6 try {
7 // The s e r v e r c r e a t e s an C a l c u l a t o r I m p l o b j e c t

2
8 Calculator c =
9 new C a l c u l a t o r I m p l ( ) ;
10
11 // I t b i n d s ( r e g i s t e r s ) t o t h e r m i r e g i s t r y
12 // s y n t a x name parameter o f r e b i n d
13 // rmi :// < host name > [ : p o r t ]/< s e r v i c e n a m e >
14 Naming . r e b i n d ( ” rmi : / / l o c a l h o s t / C a l c u l a t o r S e r v i c e ” , c ) ;
15 } catch ( E x c e p t i o n e ) {
16 System . out . p r i n t l n ( ” Trouble : ” + e ) ;
17 }
18 }
19
20 public s t a t i c void main ( S t r i n g a r g s [ ] ) {
21 new C a l c u l a t o r S e r v e r ( ) ;
22 }
23 }

You can compile the server as follow by giving the following command at a Linux shell:
1 $ javac CalculatorServer . java

The last class that we have to implement to complete our toy example is the client. The client is
implemented as follows:
1 import j a v a . n e t . MalformedURLException ;
2 import j a v a . rmi . Naming ;
3
4 public c l a s s C a l c u l a t o r C l i e n t {
5 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
6 try {
7 // B e f o r e c o n t a c t i n g t h e s e r v e r you have
8 // t o l o o k him up f i r s t
9 Calculator c = ( Calculator )
10 Naming . l ook up ( ” rmi : / / l o c a l h o s t / C a l c u l a t o r S e r v i c e ” ) ;
11
12 // We now have t h e same i n t e r f a c e as t h e s e r v e r
13 // So we can j u s t i n v o k e t h e methods l i k e t h e y were l o c a l
14 System . out . p r i n t l n ( c . add ( 4 , 5 ) ) ;
15 System . out . p r i n t l n ( c . sub ( 4 , 3 ) ) ;
16 } catch ( E x c e p t i o n e ) {
17 System . out . p r i n t l n ( ” R e c e i v e d E x c e p t i o n : ” ) ;
18 System . out . p r i n t l n ( e ) ;
19 }
20 }
21 }

The client is compiled by giving the following command at a Linux shell:


1 $ javac CalculatorClient . java

So, we are finished with the toy example. If you followed the instructions step by step, then everything
should be correct and working. To start testing this toy example you should do the following:

• Start the rmiregistry in a Linux shell: rmiregistry &

• Make sure that the rmiregsitry has access to all class files of the server

• Start your server in a new Linux shell: java CalculatorServer

• Start your client in a new Linux shell: java CalculatorClient

If you want to test this client server program in a distributed way then you have to ensure the following
point:

• On the server side you need to have the following files:

– Calculator.class
– CalculatorImpl.class

3
– CalculatorServer.class
• You should also change the address of the server that your trying to send remote method invocations
to.

• On the client side you need to have the following files:


– Calculator.class
– CalculatorClient.class

4 Exercise 3: Hotel Room Reservation System


In this exercise you are asked to program a minimal RMI client/server program. This program will be
a room reservation system using RMI. For this exercise you can assume that everybody is reserving the
room for a specific period of time. In other words, our system does not give the guests the liberty to
choose the dates for the reservation.
In addition to this, there are 5 room types with different prices.
• We have 10 rooms of type 0 which are single rooms that costs 55 Euros a night
• We have 20 rooms of type 1 which are double rooms that costs 75 Euros a night
• We have 5 rooms of type 2 which are twin rooms that costs 80 Euros a night

• We have 3 rooms of type 3 which are triple rooms that costs 150 Euros a night
• We have 2 rooms of type 4 which are quad rooms that costs 230 Euros a night
To implement this system you will have to write a server HotelServer, a client HotelClient, a
remote interface RoomManager, and the implementation of the remote interface RoomManagerImpl.
The hotel client HotelClient can be run from a Linux shell by entering the following commands:
• java HotelClient: If no options are supplied HotelClient just prints and shows how this com-
mand can be used.
• java HotelClient list <server address>: list the available number of rooms in each price
range. The output should look like the following:

– v rooms of type 0 are available for 55 Euros per night


w rooms of type 1 are available for 75 Euros per night
x rooms of type 2 are available for 80 Euros per night
y rooms of type 3 are available for 150 Euros per night
z rooms of type 4 are available for 230 Euros per night

– The values of v, w, x, y, and z should be the current number of available rooms for each
type of room.
• java HotelClient book <server address> <room type> <guest name>: books a room of
the specified type (if available), and registers the name of the guest.

• java HotelClient guests <server address>: list the names of all the registered guests
So, for the list, book, and guests options the HotelClient remotely invokes associated methods in
a remote object. The HotelClient gets the results of these remote method invocations back from the
HotelServer, and prints them out on its standard output.

You might also like