|
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...
- Package Overview
- Models & Documents
- Examples
- Comments & Notes
- For more Information...
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
- Container Services Subsytem Model (view 1)
- Jack, to what extent does this model need to be updated???
- Container Services Subsystem
Model (view 2 - TJ)
Interfaces:
- ContainerServicesUser - Any Part
that wishes to use Container Services via Messaging must implement this interface.
Classes:
- 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.
- 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
There are two ways of using a service.
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.
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.
There is 1 main interface:
- 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:
- 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:
What's the difference between GenLib.exception() and
GenLib.error()?
What was the intention of local vs. global services?
Jack, have we benchmarked the
differences between invocation methods to get a feel for how much of a difference the
different approaches actually make???
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.
- 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:
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:
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.
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 |