Controller Part 2 - Implement Remote ServicesJ8 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.

Creating 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.

Create the RemoteServicesImpl class in the remoteservices package and cut and paste the following code into it.


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 J8CaseStudy.
     */
    private static Logger log = Logger.getLogger("J8CaseStudy"); // 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 {
        // Dynamic proxy rather than use deprecated static stubs & rmic
        exportObject(stockObj, rmiPort);
        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 The run mode we are running in
     * 
     * @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);
        } 
    }
}

The following screenshot shows the remoteservices package structure after adding the RemoteServicesImpl class.

remote services implementation
Screenshot 1. The remoteservices package after adding the RemoteServicesImpl class.

Lesson 13 Complete

In this lesson we coded the RemoteServicesImpl class.

Related Java Tutorials

Fundamentals - Primitive Variables
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
OO Concepts - Encapsulation
Exceptions - Handling Exceptions
API Contents - Inheritance - Using the package keyword
API Contents - Inheritance - Using the import keyword
Swing - RMI - Serialization

What's Next?

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