Controller Part 2 - Implement Remote ServicesS2C Home « Controller Part 2 - Implement Remote Services

In this lesson we take a second look at the controller part of the MVC paradigm and implement the RemoteServices interface. The RemoteServices interface will provide remote access to and interaction with the Manufacturer file from a remote client.

Implement Remote Services Top

Here we implement the RemoteServices interface, thus providing remote access to and interaction with the Manufacturer file from a remote client. The implementation acts as a service layer between the Manufacturer GUI and the business methods of the StockImpl class. This class is a singleton and is the only object that interacts with the StockImpl singleton and therefore the only direct user of the locking/unlocking therein. This is the controller element of the MVC paradigm.

Compiling The RemoteServicesImpl Class Top

We will call our implementation class RemoteServicesImpl and this class will implement the RemoteServices interface. For the stocking, unstocking and search functionality requested by the stakeholder Stocking Goods Limited we will delegate functionality of these business methods to the StockImpl class. We will also have to include a method that creates a RMI server connection, for when the user has entered the GUI application with a run mode of "server". Lastly we will have to include a method that creates an RMI stub and gets a remote file handle.

Cut and paste the following code into your text editor and save it in the   c:\_Case_Study\src\remoteservices directory.


package remoteservices;

import java.io.IOException;
import java.rmi.*;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.logging.Logger;

import client.ManufacturerTableModel;
import client.RunMode;
import model.*;
import services.Services;
import services.ServicesException;


/**
 * Implementation of the RemoteServices interface providing remote access to and interaction 
 * with the Manufacturer file from a remote client and acts as a service layer between the 
 * Manufacturer GUI and the business methods of the StockImpl class. This class is a singleton 
 * and is the only object that interacts with the StockImpl singleton and therefore the only direct 
 * user of the locking/unlocking therein. This is the controller element of the MVC paradigm.
 * 
 * @author Charlie 
 * @version 1.0
 *
 */
public class RemoteServicesImpl extends UnicastRemoteObject implements RemoteServices {
    /**
     * The Logger instance through which all log messages from this class are routed.
     * Logger namespace is s2cCaseStudy.
     */
    private static Logger log = Logger.getLogger("s2cCaseStudy"); // Log output

    /**
     * A version number for the RemoteServicesImpl class so that serialisation can
     * occur without worrying about the underlying class changing between
     * serialisation and deserialisation.
     */
    private static final long serialVersionUID = 2498052502L;

    private static Services services;

    private StockImpl stock;

    public RemoteServicesImpl(StockImpl stock) throws RemoteException {
        log.entering("RemoteServicesImpl", "RemoteServicesImpl");
        this.stock = stock;
        log.exiting("RemoteServicesImpl", "RemoteServicesImpl");
    }

    /**
     * Delegate stocking to the StockImpl class.
     * 
     * @param name The name of the Manufacturer.
     * @param location The location where the Manufacturer is based.
     * @param stockOrdered The amount of stocking to order.
     * 
     * @throws RemoteException Indicates there was a problem accessing object remotely.
     * @throws StockingException Indicates stocking already done by another user.
     */
    @Override
    public void stockFromManufacturer(String name, String location, 
            int stockLevel, int stockOrdered) 
            throws RemoteException, StockingException {
        log.entering("RemoteServicesImpl", "stockFromManufacturer", 
        new Object[]{name, location, stockLevel, stockOrdered});
        // Lock, update and unlock in a single method call
        stock.stocking(name, location, stockLevel, stockOrdered);
        log.exiting("ServicesImpl", "stockFromManufacturer");
    }

    /**
     * Delegate unstocking to the StockImpl class.
     * 
     * @param name The name of the Manufacturer.
     * @param location The location where the Manufacturer is based.
     * @param stockOrdered The amount of unstocking to do.
     * 
     * @throws IOException Indicates there was a problem accessing the data.
     */
    @Override
    public void unstockBackToManufacturer(String name, String location, 
            int stockOrdered) throws IOException {
        log.entering("RemoteServicesImpl", "unstockBackToManufacturer", 
                new Object[]{name, location, stockOrdered});
        // Lock, update and unlock in a single method call
        stock.unstocking(name, location, stockOrdered);
        log.exiting("ServicesImpl", "unstockBackToManufacturer");
    }

    /**
     * Delegate search to the StockImpl class.
     * 
     * @param name The name of the Manufacturer.
     * @param location The location where the Manufacturer is based.
     * 
     * @return A ManufacturerTableModel containing all Manufacturer records pertaining to 
     * search criteria.
     * @throws ServicesException Indicates there was a problem accessing the stock.
     */
    @Override
    public ManufacturerTableModel searchManufacturers(String name, String location)
            throws RemoteException {
        log.entering("RemoteServicesImpl", "searchManufacturers", 
                new Object[]{name, location});
        try {
            log.exiting("ServicesImpl", "searchManufacturers");
            return stock.search(name, location);
        } catch (ServicesException e) {
            throw new RemoteException();
        }
    }

    /**
     * Method that creates a RMI server connection.
     *
     * @param stockObj The StockImpl remote object.
     * @param rmiPort The port number we want the server to listen on.
     * 
     * @throws RemoteException Indicates that a a server connection cannot
     * be created on this port.
     */
    public static void getServices(StockImpl stockObj, int rmiPort) 
            throws RemoteException {
        Registry r = java.rmi.registry.LocateRegistry.createRegistry(rmiPort);
        r.rebind("ManufacturerFile", new RemoteServicesImpl(stockObj));
        System.out.println(r);
    }

    /**
     * Method that creates an RMI stub and gets a remote file handle.
     *
     * @param hostname The IP or address of the host machine.
     * @param port the port the RMI Registry is listening on.
	 * @param runMode 
     * 
     * @return A Services instance.
     * 
     * @throws RemoteException Indicates that a problem occurred creating 
     *         the RMI stub.
     */
    public static Services getServices(String hostname, String port, 
            RunMode runMode) throws RemoteException {
        String url = "rmi://" + hostname + ":" + port + "/ManufacturerFile";

        try {
            services = (Services) Naming.lookup(url);
            System.out.println("Services From Remote " + services);
            return services;
        } catch (NotBoundException e) {
            System.err.println("Manufacturer File not registered: "
                    + e.getMessage());
            throw new RemoteException("Manufacturer File not registered: ", e);
        } catch (java.net.MalformedURLException e) {
            System.err.println(hostname + " is invalid: " + e.getMessage());
            throw new RemoteException("Cannot connect to " + hostname, e);
        } 
    }
}

Compiling Our Source File With the -cp and -d Options

Open your command line editor:

Change to directory  cd c:\_Case_Study\src\remoteservices

Compile RemoteServicesImpl.java using the java compiler with the -cp and -d options
  javac -cp ..\..\classes -d ..\..\classes RemoteServicesImpl.java

Using rmic On Our RemoteServicesImpl Class

Change to directory  cd c:\_Case_Study\classes

run rmic on our RemoteServicesImpl class
rmic remoteservices.RemoteServicesImpl

The following screenshot shows that we get a clean compile and also the RemoteServicesImpl class and its stub are now compiled into the classes\remoteservices directory.

compile RemoteServicesImpl

Lesson 13 Complete

In this lesson we coded the remote services Controller elements of the MVC pattern for our case study.

Related Java Tutorials

Beginning Java - Primitive Variables
Beginning Java - Conditional Statements
Beginning Java - Loop Statements
Objects & Classes - Arrays
Objects & Classes - Class Structure and Syntax
Objects & Classes - Reference Variables
Objects & Classes - Methods
Objects & Classes - Instance Variables & Scope
Objects & Classes - Constructors
Objects & Classes - Static Members
Objects & Classes - Enumerations
OO Concepts - Encapsulation
OO Concepts - Inheritance Concepts - Using the super keyword
Swing - RMI - Serialization
Exceptions - Handling Exceptions
API Contents - Inheritance - Using the package keyword
API Contents - Inheritance - Using the import keyword
Concurrency - Synchronization - Synchronized Blocks

What's Next?

In the next lesson we code the services Controller elements of the MVC pattern for our case study.