The original page is available at:

Prepared by Charlie Sawyer

Modified by Umar Kalim

Lab 1

Objective: Develop distributed Automated Teller Machine (ATM) using basic Java networking.


You will be developing a distributed Automated Teller Machine (ATM). The ATM will be hosted in a different process than the client application. The client will connect to the server using Java networking and communicate with the server using a protocol you will define. You will also use Java interfaces to add some sophistication to your remote invocations.

Functional Requirements

The ATM will simulate a real world automated teller machine.

The ATM must support the following operations:

(For now) The ATM need only support one account and the balance for that one account.

The ATM will run in its own process and will handle remote requests from a client running in some other process.


In the ATM system, the client and ATM will be running in different processes. Since the client cannot reference memory in the server process, it cannot get an actual reference to the real ATM object running on the server. Instead the client will use a proxy that presents all the behavior that characterizes an ATM. In fact, the client doesn't even need to know if the actual ATM is local or remote. This is achieved using a Java interface.

Create an ATM interface:

   public interface ATM 

Then create an ATMImplementation class that implements this interface:

   public class ATMImplementation implements ATM 

This is the actual ATM that has a reference to an instance of a class Account and manipulates its _balance. An instance of ATMImplementation will run on the server.

Unfortunately, the client won't be able to directly reference this object. So create a client proxy, ATMProxy, that also implements the ATM interface:

   public class ATMProxy implements ATM 

The implementation of the interface methods in ATMProxy won't actually manipulate any Account data. Instead, the proxy will connect to the server running the real ATM and for each call it will send a message over the network requesting that the server perform the work.

The server process will start up, create an ATMImplementation instance, and then open a socket and wait for incoming requests. When a request arrives the server will dispatch to the appropriate ATMImplementation method and reply if necessary.


The following diagram illustrates how the client operates on an ATM which is actually an ATMProxy that communicates over the network to the server and dispatches the call to the ATMImplementation.


All classes should be in the package:



Create the following ATM interface:

   public interface ATM {
      public void deposit(float amount) throws ATMException;
      public void withdraw(float amount) throws ATMException;
      public Float getBalance() throws ATMException;


Develop a class ATMImplementation that implements the ATM interface. For now the ATMImplementation can have just one Account. All transactions on the ATM act on balance of that Account.

  public class ATMImplementation implements ATM


The class Account should be the bare minimum needed to hold the state information that models a bank account. In fact, it need only be a wrapper around an appropriate primitive type that represents the balance in the account. The constructor for ATMImplementation should create an Account object with the default constructor and store a reference to it.


Now, the client wants to make calls on the ATM, perhaps withdrawing some money or checking the balance, but, the client can't actually get a reference to the ATMImplementation. Instead it will operate on an ATMProxy that implements the ATM interface. As far as the client is concerned, the instance is an ATM. It doesn't care that the ATMProxy actually connects to a remote server process and delegates the ATM methods to the remote ATMImplementation.

Develop an ATMProxy class that implements the ATM interface.

   public class ATMProxy implements ATM 

The proxy doesn't actually hold any account data as part of its state. It simply dispatches each method of the ATM interface to the remote ATMImplementation. The proxy will need to make a socket connection to the server process described below. Once a socket connection is made, the proxy gets the input and output streams from the socket. To send a message to the server, the proxy writes outgoing requests to the output stream. You may want to wrap the basic outbound stream with a convenience wrapper stream like Similarly, the proxy reads incoming responses from the input stream which may also be wrapped in another stream like

To communicate with the server you will need to define a protocol. The protocol enables the proxy to tell the server what it wants the server to do. And while the server is processing that request the proxy must wait for that response. Consider a simple String based protocol that includes the method to be executed and some String representation of any parameters for that method. Then have the proxy write the String messages directly onto the output stream obtained from the socket.


Develop a class Server that will host the ATMImplementation object. Server.main() should accept a port number as a command line parameter. This port is the port on which the Server will listen for client requests.

For example:

   C:\> java cs425.lab1.Server 7777

would tell the server to create a ServerSocket on port 7777.

Server.main should instantiate an ATMImplementation and begin listening for requests. To prepare for requests, the Server must create a ServerSocket and then begin accepting incoming connections on that ServerSocket. When a request is received from the client, the Server should read in incoming message from the socket input stream, interpret the request based on the protocol defined above and then dispatch the request to the appropriate method of its ATMImplementation object. If a response is required, the Server must then form the appropriate response message and send it back to the caller over the socket output stream.


To drive you system, create the following Client class and include this exact class with your submission:

   package cs425.lab1;
   public class Client {
      public static void main(String[] args) {
         try {
            // parse command line arguments
            String host = args[0];
            int port = Integer.parseInt(args[1]);
            ATM atm = new ATMProxy(host, port);
            // get initial account balance
            System.out.println("Balance: "+atm.getBalance());
            // make Rs. 1000 deposit and get new balance    
            System.out.println(" Depositing: 1000");
            System.out.println("Balance: "+atm.getBalance());
            // make Rs. 250 withdrawal and get new balance
            System.out.println(" Withdrawing: 250");
            System.out.println("Balance: "+atm.getBalance());
            // make Rs. 750 withdrawal and get new balance
            System.out.println(" Withdrawing: 750");
            System.out.println("Balance: "+atm.getBalance());
         } catch (ATMException ae) {
            System.out.println("An exception occurred while communicating with the ATM");

When invoking this client, specify the host and port of the server process as command line arguments. For example:

   C:\> java cs425.lab1.Client localhost 7777


To demonstrate your system you will need to start two distinct processes.

First startup the server specifying a port number to listen on.

   C:\> java cs425.lab1.Server 7777

Once the server is up and running, start up the client specifying the host and port of the server process.

   C:\>java cs425.lab1.Client localhost 7777

You should see the following output from the Client:

   Balance: 0.0
    Depositing: 1000
   Balance: 1000.0
    Withdrawing: 250
   Balance: 750.0
    Withdrawing: 750
   Balance: 0.0