org.jcon.util.service

This purpose of this page is provide a basic overview of this Package. For further information, please refer to the accompanying documents, Javadocs, or even the source. Or, ask the guru...

  1. Package Overview
  2. Models & Documents
  3. Examples
  4. Comments & Notes
  5. For more Information...
Package Overview

The purpose of the org.jcon.util.service package is to provide a simple mechanism for Parts to utilize Services without knowing the details of their implementation (ie. where they reside, etc.)  Messages (see org.jcon.util.msg) provide the means for communication.

Models & Documents

Models

  1. Container Services Subsytem Model (view 1) - Jack, to what extent does this model need to be updated???
  2. Container Services Subsystem Model (view 2 - TJ)

Interfaces:

  1. ContainerServicesUser - Any Part that wishes to use Container Services via Messaging must implement this interface.

Classes:

  1. ContainerServices - This class handles looking up services based on Service name. It will recurse up the system tree until it finds a Part which can provide this service.

    There are 2 different ways of actually using services (see below).

    Also note that this class has a concept of both global and local services, although at this time the local aspects are not turned on.
  2. ContainerMessaging - This class provides Message services for a container. Its designed to be used by ContainerServices, but may be reused elsewhere. A container hierarchy is supported.

Dependencies:

  • ContainerMessaging -
    • org.jcon.util.msg.Message
    • org.jcon.util.msg.MessageService
  • ContainerServices -
    • org.jcon.util.msg.Message
    • org.jcon.util.msg.MessageService
    • org.jcon.util.GenLib
Examples

There are two ways of using a service.

  1. Obtaining a reference to the Service Provider and working with it directly.

    This approach creates a higher degree of coupling between the Part and the Service, but is probably more efficient from a performance point of view, because the lookup only happens once.

    For example, Part A registers with a ContainerServices object that it responds to a particular Service name.

    public class PartA {

    public PartA () {

        ...
        containerServices.setPublicService("Service1", this);
        ...
    }

    public void doSomethingUseful() {...}
    }


    Part B asks the ContainerServices object to locate that service and then uses it directly.

    public class PartB {

    public PartB () {

        ...
        PartA pa = (PartA) containerServices.getService("Service1");
        pa.doSomethingUseful();
        ...
    }

    }


    Tighter coupling is evidenced by the fact that PartB has explicit knowledge of PartA, even though it doesn't know exactly where PartA resides in the system. 

    Also Note that in this example, each Part has to know how to obtain a reference the ContainerServices object.

  2. Sending a Message up the Container tree and allowing a Service Provider who can handle that message do so (if one exists).

    This latter approach yields a much looser coupling (the Message is the only direct link) although performance may degraded because we have to traverse the tree every time we want to use the service.

    For example, Part A implements MessageService:

    public class PartA implements MessageService {

    public void doSomethingUseful() {...}

    //---------- MessageService Implementation --------------
    public void serviceMessage(Message message) {
        String messageName = message.getName();
        if (messageName == "Service1") {
            doSomethingUseful();
            message.setTrue("IsValid");
        }
    }
    public MessageDef[] getServiceMessageDefs() {
        // Do this later
        return null;
    }
    }


    Part B asks the ContainerServices object to locate that service and then uses it directly.

    public class PartB implements ContainerServicesUser {

    private ContainerServices containerServices;

    //---------- ContainerServicesUser Implementation --------
    public void setContainerServices(ContainerServices services) {
    containerServices = services;
    }
    public String[] getContainerServicesInterests() {
    return new String[] {"Service1"};
    }
    }


    PartB can then send a Message up the tree like this...

    containerServices.sendMessage(new Message("Service1"));

    and the message will be delivered!

    Notice that in this example, neither Part has to know how to obtain a reference to containerServices. Part A is just a regular 'ol MessageListener, and PartB simply implements ContainerServicesUser. 

    The actual reference to the  containerServices object is provided by the kernel--when PartB is added to the container heirarchy, the kernel recognizes that it implements ContainerServicesUser, and thus passes in a reference to the master ContainerServices object.


    It is obvious that there is much looser coupling here between Parts, which consequently makes them more reusable.

Comments & Notes

There is 1 main interface:

  1. ContainerServicesUser - This interface is used by a Part which wishes to utilize ContainerServices. By implementing this interface, the Kernel will provide the implementer with a reference to the ContainerServices object, which it can then use to send Messages up the system tree.

There are 2 key classes:

  1. ContainerServices - This class provides services to container members. Its goal is to allow Application/Services architecture to be easily implemented in a reasonably mature manner. The following features are supported:
    • Services are named and can be any Object. They do not have to implement or extend anything.
    • Container services are hierarchially organized. This allows systems to be composed of subsystems and avoids a simplistic global services design.
    • Add or remove public or local services from a container.
    • "Upper" public services are inherited.
    • A service can be local to only that container.
    • Public services can be shadowed.
    • Local services shadow public services.
    • getService(name) is completely automatic and transparent.
    • Messages may be used instead of object lookups. This was a late modification but is preferred. We may modify this class and the system to use only Messages. All new uses of this class should use Messages.

    Later we may add methods such as getServicesList(), findService(criteria) or addContainerServicesListener().

    NOTES - We have disabled local services since they are not used and are potentially confusing. Messaging does not have any local notion. We need to design a way to determine what Message structure is needed to use MessageListener services, such as MessageProcessor with processMessage(Message) and getMessageDefs() for the Messages it processes.

    Notes:

    • implements Serializable

    • GenLib.exception(methodID, message) is only external dependency besides Message and MessageService.

    • There are two ways of using a service...either by obtaining a reference to the service provider and then invoking methods directly, or by using Messages in conjunction with the ContainerServices approach.

    Questions / Issues:

    1. What's the difference between GenLib.exception() and GenLib.error()?

    2. What was the intention of local vs. global services?

    3. Jack, have we benchmarked the differences between invocation methods to get a feel for how much of a difference the different approaches actually make???

    4. Hmmm....I wonder how Jini handles service type things...is it messaging based? Or is it through direct links... I'll have to look into this.

  2. ContainerMessaging - This class primarily plays a supporting role for ContainerServices, although it could be used elsewhere if desired. In a nutshell, its the object used by ContainerServices to keep track of MessageServices (called handlers in the code) and send them Messages.

    Notes:

    •  

    Questions / Issues:

    1. Rather than using setMessageHandler(), etc. it might make more sense to use method names like setMessageService() or something similar. I found myself looking for a MessageHandler class on several occasions, only to realize after a few moments that it didn't exist.

Misc Questions / Issues:

  1. Note that org.jcon.util.service is dependant on org.jcon.util.msg, but not the other way around. This indicates that the latter belongs to a lower layer, and is an excellent example of good design; Messages know nothing about the ContainerServices, which uses them.

For more Information...

If you are a developer and make changes to any of the models or source in this package, remember that you must update this document as well!

If you have questions, comments, or suggestions for improvement, please feel free to contact one of the folks listed below. 


Package Author/Guru: Jack Harich
Last Updated: Christian Cryder, 5/19/99