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

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

Create the ServicesImpl class in the services package and cut and paste the following code into it.


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 J8CaseStudy.
     */
    private static Logger log = Logger.getLogger("J8CaseStudy"); // 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. 
     * 
     */
    private ServicesImpl(Services services) { 
        log.entering("ServicesImpl", "ServicesImpl", new Object[]{services});
    	ServicesImpl.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 ServicesException Indicates there was a problem accessing the data.
     */
    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);
        }
    }
}

The following screenshot shows the services package structure after adding the ServicesImpl class.

services implementation
Screenshot 1. The services package after adding the ServicesImpl class.

Lesson 14 Complete

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

Related Java Tutorials

Fundamentals - Primitive Variables
Fundamentals - if Construct
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.