Spec Index | A Collection of Jini Technology Helper Utilities and Services Specifications |
Version 3.0 |
JU - JiniTM Join Utilities Specification
JU.1 Introduction
This specification defines helper utility classes, along with supporting interfaces and classes, that encapsulate functionality that can help JiniTM technology-based services (Jini services) demonstrate good behavior in their discovery and registration related interactions with Jini lookup services. In particular, the Jini join utilities perform functions related to lookup service discovery and registration (joining), as well as lease renewal and attribute management, which the Jini technology programming model requires of a well-behaved Jini service. Currently, this specification defines only one helper utility class:
JU.2 The
JoinManager
The goal of any well-behaved Jini service, implemented within the bounds defined by the Jini technology programming model, is to advertise the service it provides by requesting residency within at least one Jini lookup service. Making such a request of a Jini lookup service is known as registering with, or joining, a lookup service. To demonstrate this good behavior, a service must comply with both the multicast discovery protocol and the unicast discovery protocol to discover the lookup services it is interested in joining. The service must also comply with the join protocol to register with the desired lookup services. The details of the discovery and join protocols are described in the Jini Technology Discovery and Join Specification.
For the service to maintain its residency in the lookup services it has joined, the service must provide for the coordination, systematic renewal, and overall management of all leases on that residency. In addition to handling all discovery and join duties, as well as managing all leases on lookup service residency, the service must provide for the coordination and management of any attribute sets with which it may have registered.
With respect to the duties described above, a Jini service may perform all but the attribute set management duties by using the helper utility classes
LookupDiscoveryManager
andLeaseRenewalManager
. (For information on these classes, refer to the Jini Discovery Utilities Specification, Section DU.5, "The LookupDiscoveryManager Utility", and the Jini Lease Utilities Specification, Section LM.2, "The LeaseRenewalManager").Rather than writing a service to use these classes in a coordinated fashion (in addition to providing for attribute management), the service may be written to employ the
JoinManager
class from thenet.jini.lookup
package. This utility class performs all of the functions related to discovery, joining, service lease renewal, and attribute management that the Jini technology programming model requires of a well-behaved Jini service. Each of these activities is intimately involved with the maintenance of a service's residency in one or more lookup services (the service's join state), hence the nameJoinManager
.The
JoinManager
class provides an implementation of the functionality described above. The use of this class in a wide variety of services can help minimize the work resulting from having to repeatedly implement this required functionality in each service.The
JoinManager
is a utility class, not a remote service. Jini services that wish to use this utility will create an instance of theJoinManager
in the service's address space to manage the entity's join state locally.Note that when either the term service or the term entity is used, it refers to the object that has created an instance of the
JoinManager
and avails itself of the public methods of that utility class.JU.2.1 Other Types
The types defined in the specification of the
JoinManager
utility class are in thenet.jini.lookup
package. The following types may be referenced in this chapter. Whenever referenced, these object types will be referenced in unqualified form:net.jini.core.lease.Lease net.jini.core.entry.Entry net.jini.core.lookup.ServiceID net.jini.core.lookup.ServiceRegistrar net.jini.core.lookup.ServiceRegistration net.jini.config.Configuration net.jini.config.ConfigurationException net.jini.discovery.DiscoveryListener net.jini.discovery.DiscoveryManagement net.jini.lookup.entry.ServiceControlled net.jini.lease.LeaseRenewalManager net.jini.discovery.LookupLocatorDiscovery net.jini.discovery.LookupDiscoveryManager java.io.IOException java.io.Serializable java.rmi.MarshalledObject java.util.EventListenerJU.3 The Interface
The public methods provided by the
JoinManager
class are as follows:package net.jini.lookup; public class JoinManager { public JoinManager(Object serviceProxy, Entry[] attrSets, ServiceIDListener callback, DiscoveryManagement discoveryMgr, LeaseRenewalManager leaseMgr) throws IOException {...} public JoinManager(Object serviceProxy, Entry[] attrSets, ServiceIDListener callback, DiscoveryManagement discoveryMgr, LeaseRenewalManager leaseMgr, ConFiguration config) throws IOException, ConfigurationException {...} public JoinManager(Object serviceProxy, Entry[] attrSets, ServiceID serviceID, DiscoveryManagement discoveryMgr, LeaseRenewalManager leaseMgr) throws IOException {...} public JoinManager(Object serviceProxy, Entry[] attrSets, ServiceID serviceID, DiscoveryManagement discoveryMgr, LeaseRenewalManager leaseMgr, ConFiguration config) throws IOException, ConfigurationException {...} public DiscoveryManagement getDiscoveryManager() {...} public LeaseRenewalManager getLeaseRenewalManager() {...} public ServiceRegistrar[] getJoinSet() {...} public void replaceRegistration(Object serviceProxy){...} public void replaceRegistration(Object serviceProxy, Entry[] attrSets) {...} public Entry[] getAttributes(){...} public void addAttributes(Entry[] attrSets) {...} public void addAttributes(Entry[] attrSets, boolean checkSC) {...} public void setAttributes(Entry[] attrSets) {...} public void modifyAttributes(Entry[] attrSetTemplates, Entry[] attrSets) {...} public void modifyAttributes(Entry[] attrSetTemplates, Entry[] attrSets, boolean checkSC) {...} public void terminate() {...} }JU.4 The Semantics
The
TheJoinManager
helper utility class defines a number of public methods in addition to the constructor. This utility defines an accessor method that allows the entity to retrieve the set of lookup services with which the entity has been registered (by theJoinManager
), as well as methods that allow the entity to retrieve references to the objects theJoinManager
uses for discovery management and lease renewal management. This utility also defines a method that allows the entity to register a new reference to the service (optionally, with new attributes) which was previously registered, by this utility, with all discovered lookup services. Finally, theJoinManager
class defines methods the entity may use to manage the attributes associated with the entity, and a method that allows the entity to terminate the join processing being performed on its behalf.equals
method for theJoinManager
class returnstrue
if and only if two instances of this class refer to the same object. That is,x
andy
are equal instances of this class if and only if x == y has the valuetrue
.The constructor of the
JoinManager
class has four versions. Each version of the constructor throwsIOException
because construction of aJoinManager
may initiate the multicast discovery process, which can throwIOException
.The four versions of the constructor can be divided into two categories, each containing two of the four versions. Each category of constructor is distinguished by how the constructors in the category handle processing related to the service ID. Additionally, the only difference between the two constructors within either category is the absence or presence of a parameter of type
Configuration
, which is used to classify the constructors of the category as non-configurable or configurable, respectively.Constructors in the first category each have the following parameters in common:
- A reference (proxy) to the service requesting the services of the
JoinManager
- An array containing the service's attributes
- A reference to an object that implements the
ServiceIDListener
interface (belonging to the packagenet.jini.lookup
)
- A reference to an object that implements the
DiscoveryManagement
interface
- An instance of the
LeaseRenewalManager
utility classIf the reference to the service to be registered is not
Serializable
, anIllegalArgumentException
is thrown.Passing
null
as the value of theattrSets
parameter is equivalent to passing an emptyEntry
array. If any of the elements of theattrSets
array arenull
, aNullPointerException
is thrown.The assignment of a service ID to the service will result in an event notification being sent to the listener object that was passed as the
ServiceIDListener
argument (callback
). If anull
value is passed in through this argument, then no such notification will be sent.To use the
JoinManager
, the service supplies an object through which notifications that indicate a lookup service has been discovered or discarded will be received. At a minimum, this object must satisfy the contract defined in theDiscoveryManagement
interface. That is, this object must provide theJoinManager
with the ability to set discovery listeners and to discard previously discovered lookup services when they are found to be unavailable.The
DiscoveryManagement
argument may be set to a value ofnull
. Ifnull
is the value of this argument, then an instance of theLookupDiscoveryManager
utility class will be constructed to listen for events announcing the discovery of only those lookup services that are members of the public group, unless, in the case of either configurable version of the constructor, this default behavior is overridden through the use of the configuration mechanism (see below).The
LeaseRenewalManager
argument may be set to a value ofnull
. Ifnull
is the value of this argument, an instance of theLeaseRenewalManager
class will be created, initially managing noLease
objects. This feature allows a service that employs theJoinManager
either to use a single entity to manage all of its leases, or to use separate entities: one to manage the leases unrelated to the join process, and one to manage the leases that result from the join process and that are accessible only within theJoinManager
.A constructor from the first category is typically used by services that have not yet been assigned a service ID, but that have been pre-configured to join lookup services that the service identifies through the initialization of a discovery manager.
The constructors from the second category each take the same arguments as the constructors from the first category, except that an instance of
ServiceID
replaces the instance ofServiceIDListener
. Note that theServiceID
class is defined in the Jini Technology Lookup Service Specification, and theServiceIDListener
interface is described later in this document.Constructors from the second category each apply the same semantics to the
serviceProxy
,attrSets
,discoveryMgr
, andleaseMgr
arguments as is applied by the constructors from the first category.A constructor from the second category should be used by services that have already been assigned a service ID (possibly by the service provider or as a result of a prior registration with some lookup service), and that may or may not have been pre-configured to join lookup services identified by group or by specific location.
As previously noted, the configurable form of a constructor from either category is characterized by an additional parameter of type
Configuration
. Through that parameter, the configurable form of the constructor can be used to customize the behavior of the resultingJoinManager
instance. Such customizations are implementation dependent. ANullPointerException
is thrown ifnull
is passed as the value of that parameter. AConfigurationException
is thrown to indicate that a problem occurred while attempting to retrieve an item from the givenConfiguration
.Creating a
JoinManager
using the non-configurable form of a constructor from either category will result in aJoinManager
having only basic, default behavior. Thus, the use of the configurable forms of the constructor is strongly encouraged.The
getDiscoveryManager
method returns the instance ofDiscoveryManagement
that was either passed into the constructor by the entity or that was created as a result ofnull
being passed as that parameter. This method takes no arguments as input.The object returned by this method encapsulates the mechanism by which either the
JoinManager
or the entity itself can set discovery listeners and discard previously discovered lookup services when they are found to be unavailable.The
getLeaseRenewalManager
method returns an instance of theLeaseRenewalManager
class. This method takes no arguments as input.The object returned by this method manages the leases requested and held by the
JoinManager
. Although it may also manage leases unrelated to the join process that are requested and held by the service itself, the leases with which theJoinManager
is concerned are the leases that correspond to the service registration requests theJoinManager
has made with each lookup service the service wishes to join.The
getJoinSet
method returns an array ofServiceRegistrar
objects, each corresponding to a lookup service with which the service is currently registered (joined). If there are no lookup services with which the service is currently registered, this method returns the empty array. This method takes no arguments as input and will return a new array upon each invocation.The
replaceRegistration
method registers a new reference to the service with all current and future discovered lookup services. The new service reference will replace the reference that was previously registered as a result of either constructing this utility, or a prior invocation ofreplaceRegistration
. The new service reference will be registered using the sameServiceID
with which previous registrations were made through this utility.There are two forms of the
replaceRegistration
method. Both forms of this method take as input anObject
(serviceProxy
) that represents the new service reference (proxy) to register with each discovered lookup service. With respect to either form of thereplaceRegistration
method, if theObject
input to this parameter is notSerializable
, then anIllegalArgumentException
is thrown. Ifnull
is input to that parameter, then aNullPointerException
is thrown.The attribute sets that the first form of
replaceRegistration
associates with the new service reference are the same attribute sets as those associated with the old registration.In addition to the
serviceProxy
parameter, the second form of thereplaceRegistration
method takes an array ofEntry
objects (attrSets
), none of whose elements may benull
, that represents the new set of attributes to associate with the new service reference to be registered. As with the constructor to this utility, passingnull
as the value of theattrSets
parameter is equivalent to passing an empty array, and if any of the elements of the array arenull
, aNullPointerException
is thrown. This new set of attributes will be associated with the service in all future join processing.The registration of the new service reference with each lookup service must be performed asynchronously, thus there is no guarantee that the replacement of the old service reference with the new service reference (along with new attributes when the second form of the method is used) will have completed upon return from
replaceRegistration
. Because there is no guarantee that service registration will have completed upon return from this method, services that invoke the second form of this method must take care not to modify the contents of the array input to theattrSets
parameter. Doing so could cause the service's attribute state to be corrupted or inconsistent on a subset of the lookup services with which the service is registered as compared with the state reflected on the remaining lookup services. It is for this reason that the effects of modifying the contents of the array input to theattrSets
parameter, after the second form of this method is invoked, are undefined.The
getAttributes
method returns an array containing the set of attributes currently associated with the service. If the service is not currently associated with an attribute set, this method returns the empty array. This method takes no arguments as input and will return a new array upon each invocation.Note that although a new array is returned by
getAttributes
, the elements of that array are not copies. Thus, it is important that the elements of the array returned bygetAttributes
not be modified; doing so could cause the state of theJoinManager
to become corrupted or inconsistent. This potential for corruption or inconsistency is why the effects of modifying the elements of the array returned bygetAttributes
are undefined.The
addAttributes
method associates a new set of attributes with the service, in addition to the service's current set of attributes. The association of this new set of attributes with the service will be propagated to each lookup service with which the service is registered. This propagation must be performed asynchronously, so there is no guarantee that the propagation of the attributes to all lookup services with which the service is registered will have completed upon return from this method.The set of attributes consisting of the union of the new set with the old set will be associated with the service in all future join processing.
There are two forms of the
addAttributes
method. Both forms of this method take as input an argument (attrSets
) representing the set of attributes to associate with the service. This set is represented as an array ofEntry
objects, none of whose elements may benull
. If at least one element of this input set isnull
, aNullPointerException
is thrown.An invocation of either form of this method with duplicate elements in the
attrSets
parameter (where duplication means attribute equality as defined by calling theMarshalledObject.equals
method on field values) is equivalent to performing the invocation with the duplicates removed from that parameter. Ifnull
is passed in as the value of this parameter, aNullPointerException
will be thrown.The second form of this method also takes as input a flag indicating whether or not this method should determine if the attributes in the input set are instances of the
ServiceControlled
interface, which is a marker interface that is used to control which entities may modify a service's attribute set. For more information on this interface, refer to the Jini Lookup Attribute Schema Specification, Section LS.4.1, "Indicating User Modifiability". If the value of this flag is true and at least one of the attributes to be added is an instance of theServiceControlled
interface, aSecurityException
will be thrown and propagated through this method.Note that because there is no guarantee that attribute propagation will have completed upon return from this method, services that invoke this method must take care not to modify the contents of the input array. Doing so could cause the service's attribute state to be corrupted or inconsistent on a subset of the lookup services with which the service is registered as compared with the state reflected on the remaining lookup services. It is for this reason that the effects of modifying the contents of the input array, after this method is invoked, are undefined.
The
setAttributes
method replaces the service's current set of attributes with the given new set of attributes. This method takes a single argument as input: an array ofEntry
objects, none of whose elements may benull
, which represents the set of attributes that will replace the current set of attributes. If at least one element of this input set isnull
, aNullPointerException
is thrown.The replacement of the service's current set of attributes with the new set of attributes will be propagated to each lookup service with which the service is registered. This propagation must be performed asynchronously, so there is no guarantee that the propagation of the attributes to all lookup services with which the service is registered will have completed upon return from this method.
The service's new set of attributes will be associated with the service in all future join processing.
An invocation of this method with duplicate elements in the
attrSets
parameter (where duplication means attribute equality as defined by calling theMarshalledObject.equals
method on field values) is equivalent to performing the invocation with the duplicates removed from that parameter. Ifnull
is input tosetAttributes
, aNullPointerException
will be thrown.For the same reason as noted above in the description of the
addAttributes
method, the effects of modifying the contents of the input array after the methodsetAttributes
is invoked, are undefined.The
modifyAttributes
method changes the service's current set of attributes using the same semantics as themodifyAttributes
method of the classServiceRegistration
(see the Jini Technology Lookup Service Specification). This method has two forms. The first form takes two arguments, the second form takes three arguments. Both forms will take an array of templates in the first argument and an array of attributes in the second argument. The templates are used to identify which elements to modify from the service's current set of attributes. If any element of the array of templates isnull
, aNullPointerException
is thrown. The attribute array contains the actual modifications to be made. The additional argument in the signature of the second form ofmodifyAttributes
is a flag indicating whether or not this method should determine if the attributes in the input set are instances of theServiceControlled
interface, which is a marker interface used to control which entities may modify a service's attribute set (see the Jini Lookup Attribute Schema Specification, Section LS.4.1, "Indicating User Modifiability"). If the value of this flag is true and at least one of the attributes to be modified is an instance of theServiceControlled
interface, aSecurityException
will be thrown and propagated through this method.The association of the new set of attributes with the service will be propagated to each lookup service with which the service is registered. This propagation must be performed asynchronously. Because of this asynchronous behavior, there is no guarantee that the propagation of the attributes to all lookup services with which the service is registered will have completed upon return from this method.
The set of attributes that results after the modifications have been applied will be associated with the service in all future join processing.
The
modifyAttributes
method throws anIllegalArgumentException
if one of the following conditions is satisfied:
- The length of the array containing the templates does not equal the length of the array containing the attributes
- Any element of either array is not an instance of a valid
Entry
class (for example, the class is not public, does not contain a no-arg constructor, or has at least one public field which is a non-static, non-final primitive)
- The class of
attrSets[
i
]
is neither the same as, nor a super class of, the class ofattrSetsTemplate[
i
]
For the same reason as that noted above in the description of the
addAttributes
method, the effects of modifying the contents of theattrSets
parameter, aftermodifyAttributes
is invoked, are undefined.The
terminate
method performs cleanup duties related to the termination of the lookup service discovery event mechanism, as well as to the lease and thread management performed by theJoinManager
. This method will cancel all of the service's managed leases that were granted by the lookup services with which the service is registered, and will terminate all threads that have been created.If the discovery manager employed by the
JoinManager
was created by theJoinManager
itself, this method will terminate all discovery processing being performed by that manager object on behalf of the service; otherwise, the discovery manager supplied by the service is still valid.Whether an instance of the
LeaseRenewalManager
class was supplied by the service or created by theJoinManager
itself, any reference to that object obtained by the service prior to termination will still be valid after termination.The
JoinManager
makes certain concurrency guarantees with respect to an invocation of theterminate
method while other method invocations are in progress. The termination process described above will not begin until completion of all invocations of the methods defined in the public interface of theJoinManager
. The semantics of all current and future method invocations made on an instance ofJoinManager
after that instance has been terminated are left for eachJoinManager
implementation to define (although the reference to theLeaseRenewalManager
object employed by anyJoinManager
instance is still valid, even after termination). For example, aJoinManager
implementation might be defined to throwIllegalStateException
when any method on thatJoinManager
is invoked after the termination process has completed.JU.5 Supporting Interfaces and Classes
The
JoinManager
class depends on the interfacesDiscoveryManagement
andServiceIDListener
discussed below.
JoinManager
also references the concrete classesLookupDiscoveryManager
andLeaseRenewalManager
, each described in a separate specification.JU.5.1 The
DiscoveryManagement
InterfaceAlthough it is not necessary for the
JoinManager
itself to execute the discovery process, it does need to be notified when one of the lookup services it wishes to join is discovered or discarded. Thus, at a minimum, theJoinManager
requires access to the discovery events sent to the listeners registered with the discovery process' event mechanism. The instance ofDiscoveryManagement
that is passed as an argument to the constructor of theJoinManager
provides a mechanism for acquiring access to those events. For a complete description of the semantics of the methods of this interface, refer to the Jini Discovery Utilities Specification.One noteworthy item about the semantics of the
JoinManager
is the effect that invocations of thediscard
method ofDiscoveryManagement
will have on any discovery listeners created by theJoinManager
. TheDiscoveryManagement
interface specifies that thediscard
method will remove a particular lookup service from the managed set of lookup services that have already been discovered, allowing that lookup service to be rediscovered. Invoking this method will result in the flushing of the lookup service from the appropriate cache, ultimately causing a discard notification to be sent to allDiscoveryListener
objects registered with the event mechanism of the discovery process, including all listeners registered by theJoinManager
.Upon receipt of an event notification indicating that a lookup service has been discarded, the lease granted by the discarded lookup service is ultimately cancelled. Note that although a discarded event is sent when the lookup service is no longer available, such an event will also be sent whenever the lookup service is available, but the service no longer wishes to be registered with the lookup service. (For example, the service's groups of interest may have been changed so that they no longer include any of the lookup service's member groups.) In this case, cancelling the lease can produce consistent system state in a much more timely fashion than simply allowing the lease to expire.
JU.5.2 The
ServiceIDListener
InterfaceThe
ServiceIDListener
interface defines the methods used by a service to register a request for notification from theJoinManager
upon the assignment of aserviceID
by a lookup service. It is the responsibility of the service to create and pass into theJoinManager
an object that implements this interface. That implementation must provide the definition of the actions to take upon receipt of the notification. Typically, the action taken will be to persist the assignedserviceID
reference.package net.jini.lookup; public interface ServiceIDListener extends EventListener { public void serviceIDNotify(ServiceID serviceID); }The intent of this interface is to allow the entity to receive the
ServiceID
instance assigned to it by the lookup service. It is not part of the semantics of the call that the return from theServiceIDNotify
method can be delayed while the recipient of the call processes the information delivered by the method. Thus, it is highly recommended that implementations of this interface avoid time consuming operations, and return from the method as quickly as possible. For example, one strategy might be to simply notify a separate thread, operating asynchronously, which is designed to place theServiceID
instance in persistent storage.JU.6 History
Version Description v1.0 Initial release of this specification. v2.0 New constructors added to accommodate configuration, along with supporting text. Miscellaneous corrections. v3.0 Add specification for the replaceRegistration
method.
SpecifyRuntimeExceptions
that are thrown by the methods of this utility.
Specify that the lease from a discarded lookup service should be cancelled, not removed (as was previously specified).
Miscellaneous corrections and clarifications.License
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Spec Index | A Collection of Jini Technology Helper Utilities and Services Specifications |