The Registry Service is one of several framework-specific services provided to all components. The main aim of this service is to enable collaboration between component instances.
On creation, instances which are desired to be shared can register themselves through this service. Other instances can use the service to look up registered instances and get a handle to use their interfaces. This allows easy collaboration in distributed environments.
The registry service itself is a front-end to the instance information. There can be any number of service providers that plug in to actually store the instance data. The user of this service can make calls on various sources of instance information without being aware of the mechanism used for storage and protocol used for data transfer.
Information in the registry is logically stored in a hierarchy. This hierarchy is similar to a file system hierarchy, and its form is dictated by the structure of the URL identifying a component instance. Users can store and retrieve instance information in the registry and can navigate the registry hierarchy to identify the instance they are interested in.
Back to top
interface RegistryService : CCAPort {
RegistryContext getContext(in string context)
raises (NotFoundException, BadContextNameException);
};
valuetype RegistryNode {
string getName();
short isInstance();
short isContext();
};
valuetype RegistryContext : RegistryNode {
typedef sequence < InstanceInfo > InstanceInfoSeq;
typedef sequence < RegistryNode > RegistryNodeSeq;
InstanceInfoSeq lookup(in string instance_name)
raises (NotFoundException, InvalidContextException);
RegistryContext getSubContext(in string subcontext)
raises (BadContextNameException, InvalidContextException, NotFoundException);
RegistryNodeSeq getChildren() raises (InvalidContextException);
InstanceInfoSeq getAllInstances() raises (InvalidContextException);
void bind(in ComponentID id, in string instance_name, in EnvObj env,
in InformationInfo component_info) raises (InvalidContextException);
void bind(in InstanceInfo instance_info, in string instance_name)
raises (InvalidContextException);
void unbind(in ComponentID id) raises (NotFoundException);
};
valuetype Info {
typedef sequence < Info > InfoSeq;
typedef sequence < String > StringSeq;
StringSeq getValue(in string key);
InfoSeq getInfo(in string key);
StringSeq getKeys();
};
valuetype InstanceInfo : RegistryNode, Info {
ComponentID getComponentID();
};
class RegistryService : public CCAPort {
public:
virtual RegistryContext getContext(char* context)
throw (NotFoundException, BadContextNameException) = 0;
};
class RegistryNode {
public:
virtual char* getName() = 0;
virtual int isInstance() = 0;
virtual int isContext() = 0;
};
class RegistryContext : public RegistryNode {
public:
virtual InstanceInfo** lookup(char* instance_name, int &length)
throw (NotFoundException, InvalidContextException) = 0;
virtual RegistryContext getSubContext(char* subcontext)
throw (BadContextNameException, InvalidContextException, NotFoundException) = 0;
virtual RegistryNode** getChildren(int &length)
throw (InvalidContextException) = 0;
virtual InstanceInfo** getAllInstances(int &length)
throw (InvalidContextException) = 0;
virtual void bind(ComponentID* id, char* instance_name, EnvObj* env,
InformationInfo component_info) throw (InvalidContextException) = 0;
virtual void bind(InstanceInfo* instanceInfo, char *instance_name)
throw (InvalidContextException) = 0;
virtual void unbind(ComponentID* id) throw (NotFoundException) = 0;
};
class Info {
virtual char** getValue(char* key) const = 0;
virtual Info** getInfo(char* key, int &length) const = 0;
virtual char** getKeys() const = 0;
};
class InstanceInfo : public RegistryNode, public Info {
virtual ComponentID* getComponentID() const = 0;
};
interface RegistryService extends CCAPort {
public RegistryContext getContext(String context)
throws NotFoundException, BadContextNameException;
}
interface RegistryNode {
public String getName();
public int isInstance();
public int isContext();
}
interface RegistryContext extends RegistryNode {
public InstanceInfo [] lookup(String instance_name)
throws NotFoundException, InvalidContextException;
public RegistryContext getSubContext(String subcontext)
throws BadContextNameException, InvalidContextException, NotFoundException;
public RegistryNode [] getChildren() throws InvalidContextException;
public InstanceInfo [] getAllInstances() throws InvalidContextException;
public void bind(ComponentID id, String instanceName, EnvObj env,
InformationInfo componentInfo) throws InvalidContextException;
public void bind(InstanceInfo instanceInfo, String instanceName)
throws InvalidContextException;
public void unbind(ComponentID id) throws NotFoundException;
}
interface Info {
public String [] getValue(String key);
public Info [] getInfo(String key);
public String getKeys();
}
interface InstanceInfo extends RegistryNode, Info {
ComponentID getComponentID();
}
getContext(in string context) [1]
This returns a context value object that can be used to look up instance information. context is any prefix of the full URL name. Examples are:
http://rainier:3434/cca/
ldap://moose:1234/
file://l/extreme/dir_containing_instance_info/
This method raises a NotFoundException if the specified context does not correspond to an actual registry.
string getName()
This returns the name of the current node.
C++ Semantics
int isContext()
Returns 0 if this node cannot be used as a RegistryContext, 1 if it can.
int isInstance()
Returns 0 if this node cannot be used as an InstanceInfo, 1 if it can.
InstanceInfo [] lookup(in string instance_name)
[2]
This returns a list of value objects which encapsulate information about instances. instance_name is the full URL for the instance starting from the current context, for example:
/components/cca/lsa/NewSystem/MyInstance
A list is returned from this method since the instance_name used for the lookup is the user provided instance name given at the time of binding the instance to the registry, and it may not have been unique.
This method raises a NotFoundException if there was no instance with the specified name stored in the registry. It raises an InvalidContextException if for some reason the current context being used was no longer valid.
C++ Binding Only:
C++ Semantics
RegistryContext getSubContext(in string subcontext)
This returns a RegistryContext for the provided subcontext path. The subcontext path starts from the current context. This allows the user to then navigate through the instance hierarchy starting from the new context if they so wished.
This method raises a BadContextNameException if the specified subcontext corresponds to a non-leaf node in the instance hierarchy. It raises a NotFoundException if the specified subcontext did not correspond to a node in the instance hierarchy. It raises an InvalidContextException if the current context being used became invalid for some reason.
RegistryNode [] getChildren ()
This method returns information about the immediate children of this context in the instance hierarchy.
An InvalidContextException will be raised if for some reason the context being used becomes invalid.
C++ Binding Only:
C++ Semantics
InstanceInfo [] getAllInstances()
This will return information on all instances in the hierarchy that appear in this context.
An InvalidContextException will be raised if the context becomes invalid.
C++ Binding Only:
C++ Semantics
void bind(in ComponentID id, in string instance_name, in EnvObj env, in InformationInfo component_info) [3]
This binds the given id to the specified instance_name. The env contains name-value pairs with information about this instantiation which may be useful to the user. The component_info contains port type information and other details required to be associated with the instance when it is bound.
An InvalidContextException will be raised if the context becomes invalid.
The EnvObj used in this call must have the following information. The names used to lookup the information in the env object are specified in parentheses.
For details on the contents of component information, take a look at the Information Directory Service API.
If bind succeeds, it will generate an InstanceBound event.
void bind(in InstanceInfo instance_info, in string instance_name) [3]
This binds the instance described by instance_info to the specified instance_name.
An InvalidContextException will be raised if the context becomes invalid.
If bind succeeds, it will generate an InstanceBound event.
void unbind(in ComponentID id)
This method unbinds the specified instance from the registry. The id is the component ID of the instance to be unbound.
If unbind succeeds, it will generate an InstanceUnbound event.
This methods raises a NotFoundException if the provided id does not correspond to any instance stored in the registry.
String [] getValue()
This method will be used for looking up key-value pairs used in describing the instance. I key may be used multiple times, in which case the array of values returned will have more than one element. If there is no match with the specified key, null will be returned. The following keys will be available in any InstanceInfo object, with the return values to be interpreted as explained below.
C++ Semantics
ComponentID getComponentID()
This will return the component ID for this instance.
Here, Component A creates an instance of Component B and adds it to the registry. Then, Component C looks up the same registry for the instance, accesses the component ID and then begins using it:
// code within component A
// look up an information directory containing component B
String idsContextURL = "http://foo";
// note that we are ignoring exceptions thrown by the information directory service/context
InformationDirectoryContext idsContext = informationDirectoryServicePort.getContext(idsContextURL);
InformationInfo componentBInfo = idsContext.lookup("componentB");
// get the environment for creation on a machine named mymachine, using gram
Env creationEnv = componentBInfo.getCreationEnv("mymachine","gram");
// create the instance
ComponentID newComponentID = creationServicePort.createInstance(componentURL,creationEnv);
// get a registry context
String registryURL = getDefaultRegistry();
RegistryContext context;
try {
context = registryServicePort.getContext(registryURL);
} catch (NotFoundException exception) {
// could not contact the server or the
// specified directory could not exist
// try another server or directory
} catch (BadContextNameException exception) {
// specified an instance name instead of a context
// try changing registryURL or try another registry
}
// bind the new instance to the registry
context.bind(newComponentID,"B_Instance",creationEnv,componentBInfo);
-------------------------------------------------------
-------------------------------------------------------
// code within component C
public ComponentID getB_Instance() {
// get a registry context
String registryURL = getDefaultRegistry(); // must be the same as component A's registry URL
RegistryContext context;
try {
context = registryServicePort.getContext(registryURL);
// get the instances with that name which are in this context
InstanceInfo [] instances = context.lookup("B_Instance");
// iterate through them and pick the one of interest
// if it is assumed there is only one instance with this name,
// instances[0] can be returned right away
for (int i=0; i < instances.length; i++) {
InstanceInfo currentInstance = instances[i];
// assume there was only one creator
if (currentInstance.getValue("creator")[0].equals("jsmith")) {
// here's the one I wanted
return currentInstance.getComponentID();
}
}
return null;
} catch (Exception exception) {
// registry URL was wrong or instance name was wrong or some such thing
return null;
}
}
Here Component A is a registry search component, a front-end to any registry which provides high-level search functionality. The method below is part of the component. Given a registry URL and a user name, it removes all instances from that registry which have been created by the given user.
// given a registry URL and username, this removes all instances under the
// specified URL (i.e. in that directory and all its children) created by the specified
// user
// returns an int with the number of objects that were destroyed
public int cleanUpInstances(String registryURL, String creator)
throws NotFoundException, BadContextException {
// get the context
RegistryContext context = registryServicePort.getContext(registryURL);
// get all the instances below this context
InstanceInfo [] instances;
try {
instances = context.getAllInstances();
} catch (InvalidContextException exception) {
// the context must have been modified before all instances could
// be retrieved
// make the caller provide an accurate URL once again
throw new NotFoundException();
}
// iterate through the instances
int numDeleted = 0;
for (int i=0; i < instances.length; i++) {
InstanceInfo currentInstance = instances[i];
// check if this is an instance of interest
if (currentInstance.get("creator")[0].equals(creator)) {
// remove this from the registry
try {
context.unbind(currentInstance.getComponentID());
numDeleted++;
} catch (NotFoundException exception) {
// can't see how this can happen, unless someone unbound
// just before i did, so just log that this happened
String warnMessage = new String("Warning: Component "+
currentInstance.getComponentID()+
" was unbound already\n");
logFileStream.write(warnMessage.getBytes());
numDeleted--;
}
}
}
return numDeleted;
}
[1] Initially binding and lookup were public methods in the RegistryService API. While this scheme was simple and easy to understand, it prevented concurrent use of the service. This is because bind and lookup calls are made relative to a specific context. Two components using the same registry service simultaneously might wish to have different registry contexts (i.e. different physical servers which store registry data). One way to enable this would be to have each user of the service pass the context as a parameter with each bind or lookup call. This solved the problem, but was cumbersome and somewhat untidy. Looking at the JNDI API gave us the idea of using a different registry context for each user of the registry service. Once the context is obtained, the user of the service would make all calls through the context. This would allow the same component to have different registry contexts, as well as allow different components use of the registry service simultaneously.
[2] Most other APIs for registry services (e.g. the API for the Java RMI registry) do not allow users to bind information using a name that has already been used. In RMI, the user needs to use an explicit rebind call to overwrite the existing information under that name. This keeps the API simple - lookup returns a single instance bound under that name, if any. The drawback of the scheme is that code using the registry is often littered with an attempt to bind, followed by a block which catches the exception thrown if the name was used and tries to rebind or just warns the user that the bind failed. The alternative to this is what we did: allowing multiple binds under a single name. The registry internally generates a unique name for each instance. When a lookup is done, all instances bound under that name are possible matches, so the user gets an array as the return value from lookup.
[3] Why do we have two forms of the bind call?
There are two ways using which a user can hold of a handle to an
instance (i.e. a ComponentID for it):
Last modified: Tue Mar 14 11:29:12 EST 2000