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

In this lesson we complete our controller code by implementing the Services interface. The Services interface will provide local access to and interaction with the Manufacturer file from a local client.

Implement ServicesTop

In this part of the lesson we implement the services interface, thus providing local access to and interaction with the Manufacturer file from a local 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 ServicesImpl Class Top

We will call our implementation class ServicesImpl and this class will implement the Services 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 calls our private constructor to ensure via double locking that we only ever have one Services instance. Lastly we will have to include a method that gets a local file handle for the StockImpl class.

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


package services;

import java.rmi.RemoteException;
import java.util.logging.*;

import client.ManufacturerTableModel;
import client.RunMode;
import model.*;
import remoteservices.RemoteServicesImpl;

/**
 * This class 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 ServicesImpl implements Services {
    /**
     * 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

    /**
     * Only create ServicesImpl Singleton first time through using double-checked 
     * locking to ensure private constructor is only synchronised once.
     */
    private volatile static Services uniqueServicesImplInstance;

    /**
     * Holds a reference to the connection type.
     */
    private static StockImpl stockImpl;

    private static Services services;
 
    /**
     * ServicesImpl Constructor constructor. 
     * 
     * @param services The Data handle. 
     * 
     * @throws RemoteException 
     *
     */
    @SuppressWarnings("static-access")
	private ServicesImpl(Services services) { 
        log.entering("ServicesImpl", "ServicesImpl", new Object[]{services});
    	this.services = services;
        log.exiting("ServicesImpl", "ServicesImpl");
    }

    /**
     * Clients of the ServicesImpl class have to call this method to get the unique
     * instance (singleton) for this class as the constructor is private.
     * 
     * @param RunMode The mode the contractor application was started in. 
     * @param fileHandle A handle to our Manufacturer file
     * @param port The port number (used in server mode)
     * 
     * @return The client singleton for ServicesImpl class.
     * 
     * @throws RemoteException 
     */
    public static Services getServicesImplInstance(RunMode runMode,  
            String fileHandle, String port) {
        log.entering("ServicesImpl", "getServicesImplInstance",
                new Object[]{runMode, fileHandle, port});
        if (uniqueServicesImplInstance == null) {
            synchronized (ServicesImpl.class) {
                if (uniqueServicesImplInstance == null) {
                    if (runMode == RunMode.NON_NETWORK_CLIENT) {
                        stockImpl = getServices(fileHandle);
                        uniqueServicesImplInstance = new ServicesImpl(services);
                    } else { 
                        try { 
                            return RemoteServicesImpl.getServices(
                                    fileHandle, port, runMode);
                        } catch (RemoteException e) {
                            throw new ServicesException(e);
                        }
                    }
                }
            }
        }
        log.exiting("ServicesImpl", "getServicesImplInstance");
        return uniqueServicesImplInstance;
    }

    /**
     * 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 stock order.
     * 
     * @throws StockingException Indicates stocking already done by another user.
     * @throws ServicesException Indicates there was a problem accessing the data.
     */
    @Override
    public void stockFromManufacturer(String name, String location, 
            int stockLevel, int stockOrdered) throws ServicesException, StockingException {
        log.entering("ServicesImpl", "stockFromManufacturer", 
                new Object[]{name, location, stockLevel, stockOrdered});
        // Lock, update and unlock in a single method call
        stockImpl.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 ServicesException Indicates there was a problem accessing the stockImpl.
     */
    @Override
    public void unstockBackToManufacturer(String name, String location,
            int stockOrdered) throws ServicesException {
        log.entering("ServicesImpl", "unstockBackToManufacturer", 
                new Object[]{name, location, stockOrdered});
        // Lock, update and unlock in a single method call
        stockImpl.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 stockImpl.
     */
    @Override
    public ManufacturerTableModel searchManufacturers(String name, String location) 
            throws ServicesException {
        log.entering("ServicesImpl", "searchManufacturers", 
                new Object[]{name, location});
        try {
            log.exiting("ServicesImpl", "searchManufacturers");
            return stockImpl.search(name, location);
        } catch (ServicesException e) {
            throw new ServicesException(e);
        }
    }

    /**
     * Method that gets a StockImpl handle, StockImpl is a local object.
     *
     * @param stockImpl The StockImpl local object.
     * 
     * @return A StockImpl instance.
     * @throws ServicesException Indicates there was a problem accessing the stockImpl.
     *  
     * For more information, see {@link StockImpl}.
     */
    public static StockImpl getServices(String stockImpl) 
            throws ServicesException {
        try {
            return model.StockImpl.getStockImplInstance(stockImpl);
        }
        catch (ManufacturerFileAccessException e) {
            throw new ServicesException(e);
        }
    }
}

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

Open your command line editor:

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

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

The following screenshot shows that we get a clean compile and also the ServicesImpl class is now compiled into the classes\services directory.

compile ServicesImpl

Lesson 14 Complete

In this lesson we coded the 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 section we finish coding the View elements of the MVC pattern for our case study.