The
ServiceDiscoveryManager
class is a helper utility class that any client-like entity can use to "discover" services registered with any number of lookup services of interest. On behalf of such entities, this class maintains - as much as possible - up-to-date state information about both the lookup services the entity wishes to query, and the services the entity wishes to acquire and use. By maintaining current service state information, the entity can implement efficient mechanisms for service access and usage.
There are three basic usage patterns for this class. In order of importance and typical usage, those patterns are:
- The entity requests that the
ServiceDiscoveryManager
create a cache (an instance of {@link net.jini.lookup.LookupCache LookupCache}) which will asynchronously "discover", and locally store, references to services that match criteria defined by the entity; services which are registered with one or more lookup services managed by the ServiceDiscoveryManager
on behalf of the entity. The cache can be viewed as a set of service references that the entity can access locally as needed through one of the public, non-remote methods provided in the cache's interface. Thus, rather than making costly remote queries of multiple lookup services at the point in time when the entity needs the service, the entity can simply make local queries on the cache for the services that the cache acquired and stored at a prior time. An entity should employ this pattern when the entity must make frequent queries for multiple services. By populating the cache with multiple instances of the desired services, redundancy in the availability of those services can be provided. Thus, if an instance of a service is found to be unavailable when needed, the entity can execute a local query on the cache rather than one or more remote queries on the lookup services to acquire an instance that is available. To employ this pattern, the entity invokes the method {@link net.jini.lookup.ServiceDiscoveryManager#createLookupCache createLookupCache}. - The entity can register with the event mechanism provided by the
ServiceDiscoveryManager
. This event mechanism allows the entity to request that it be notified when a service of interest is discovered for the first time, or has encountered a state change such as removal from all lookup services, or attribute set changes. Although interacting with a local cache of services in the way described in the first pattern can be very useful to entities that need frequent access to multiple services, some client-like entities may wish to interact with the cache in a reactive manner. For example, an entity such as a service browser typically wishes to be notified of the arrival of new services of interest as well as any changes in the state of the current services in the cache. In these situations, polling for such changes is usually viewed as undesirable. If the cache were to also provide an event mechanism with notification semantics, the needs of entities that employ either pattern can be satisfied. To employ this pattern, the entity must create a cache and supply it with an instance of the {@link net.jini.lookup.ServiceDiscoveryListener ServiceDiscoveryListener} interface that will receive instances of {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent}when events of interest, related to the services in the cache, occur. - The entity, through the public API of the
ServiceDiscoveryManager
, can directly query the lookup services managed by the ServiceDiscoveryManager
for services of interest; employing semantics similar to the semantics employed in a typical lookup service query made through the {@link net.jini.core.lookup.ServiceRegistrar ServiceRegistrar}interface. Such queries will result in a remote call being made at the same time the service is needed (unlike the first pattern, in which remote calls typically occur prior to the time the service is needed). This pattern may be useful to entities needing to find services on an infrequent basis, or when the cost of making a remote call is outweighed by the overhead of maintaining a local cache (for example, due to limited resources). Although an entity that needs to query lookup service(s) can certainly make such queries through the {@link net.jini.core.lookup.ServiceRegistrar ServiceRegistrar}interface, the ServiceDiscoveryManager
provides a broad API with semantics that are richer than the semantics of the {@link net.jini.core.lookup.ServiceRegistrar#lookup lookup} methodsprovided by the {@link net.jini.core.lookup.ServiceRegistrar ServiceRegistrar}. This API encapsulates functionality that many client-like entities may find more useful when managing both the set of desired lookup services, and the service queries made on those lookup services. To employ this pattern, the entity simply instantiates this class with the desired parameters, and then invokes the appropriate version of the {@link net.jini.lookup.ServiceDiscoveryManager#lookup lookup}method when the entity wishes to acquire a service that matches desired criteria.
All three mechanisms just described - local queries on the cache, service discovery notification, and remote lookups - employ the same template-matching scheme as that employed in the {@link net.jini.core.lookup.ServiceRegistrar ServiceRegistrar} interface.Additionally, each mechanism allows the entity to supply an object referred to as a filter; an instance of {@link net.jini.lookup.ServiceItemFilter ServiceItemFilter}. A filter is a non-remote object that defines additional matching criteria that the ServiceDiscoveryManager
applies when searching for the entity's services of interest. Employing a filter is particularly useful to entities that wish to extend the capabilities of the standard template-matching scheme.
In addition to (or instead of) employing a filter to apply additional matching criteria to candidate service proxies initially found through template matching, filters can also be used to extend the selection process so that only proxies that are safe to use are returned to the entity. To do this, the entity would use the {@link net.jini.lookup.ServiceItemFilter ServiceItemFilter} interface tosupply the ServiceDiscoveryManager
or {@link net.jini.lookup.LookupCache LookupCache} with a filter that,when applied to a candidate proxy, performs a set of operations that is referred to as proxy preparation. As described in the documentation for {@link net.jini.security.ProxyPreparer}, proxy preparation typically includes operations such as, verifying trust in the proxy, specifying client constraints, and dynamically granting necessary permissions to the proxy.
Note that this utility class is not remote. Clients and services that wish to use this class will create an instance of this class in their own address space to manage the state of discovered services and their associated lookup services locally.
@com.sun.jini.impl The following implementation-specific items are discussed below:
Configuring ServiceDiscoveryManager
This implementation of
ServiceDiscoveryManager
supports the following configuration entries; where each configuration entry name is associated with the component name
net.jini.lookup.ServiceDiscoveryManager
. Note that the configuration entries specified here are specific to this implementation of
ServiceDiscoveryManager
. Unless otherwise stated, each entry is retrieved from the configuration only once per instance of this utility, where each such retrieval is performed in the constructor.
It is important to note that in addition to allowing a client of this utility to request - through the public API - the creation of a cache that is used externally by the client, this utility also creates instances of the cache that are used internally by the utility itself. As such, in addition to the configuration entries that are used only in this utility (and not in any cache), and the configuration entries that are retrieved during the construction of each new cache (and used by only that cache), there are configuration entries specified below that are retrieved once during the construction of this utility, but which are shared with, and used by, the caches that are created.
• | cacheTaskManager |
  | Type: | {@link com.sun.jini.thread.TaskManager} |
  | Default: | new {@link com.sun.jini.thread.TaskManager#TaskManager() TaskManager}(10, (15*1000), 1.0f) |
  | Description: | The object that pools and manages the various threads executed by each of the lookup caches created by this utility. There is one such task manager created for each cache. The default manager creates a maximum of 10 threads, waits 15 seconds before removing idle threads, and uses a load factor of 1.0 when determining whether to create a new thread. For each cache that is created in this utility, a single, separate instance of this task manager will be retrieved and employed by that cache. This object should not be shared with other components in the application that employs this utility. |
• | discardTaskManager |
  | Type: | {@link com.sun.jini.thread.TaskManager} |
  | Default: | new {@link com.sun.jini.thread.TaskManager#TaskManager() TaskManager}(10, (15*1000), 1.0f) |
  | Description: | The object that pools and manages the threads, executed by a cache, that wait on verification events after a previousy discovered service has been discarded. The default manager creates a maximum of 10 threads, waits 15 seconds before removing idle threads, and uses a load factor of 1.0 when determining whether to create a new thread. For each cache that is created in this utility, a single, separate instance of this task manager will be retrieved and employed by that cache. This object should not be shared with other components in the application that employs this utility. |
• | discardWait |
  | Type: | long |
  | Default: | 2*(5*60*1000) |
  | Description: | The value used to affect the behavior of the mechanism that handles the service discard problem described in this utility's specification. This item allows each entity that uses this utility to define how long (in milliseconds) to wait for verification from the lookup service(s) that a discarded service is actually down before committing or un-committing a requested service discard. The current implementation of this utility defaults to waiting 10 minutes (twice the maximum lease duration granted by the Reggie implementation of the lookup service). Note that this item is used only by the caches (both internal and external) that are created by this utility, and not by the utility itself. |
• | discoveryManager |
  | Type: | {@link net.jini.discovery.DiscoveryManagement} |
  | Default: | new {@link net.jini.discovery.LookupDiscoveryManager#LookupDiscoveryManager(java.lang.String[],net.jini.core.discovery.LookupLocator[],net.jini.discovery.DiscoveryListener,net.jini.config.Configuration) LookupDiscoveryManager}( new java.lang.String[] {""}, new {@link net.jini.core.discovery.LookupLocator}[0], null, config) |
  | Description: | The object used to manage the discovery processing performed by this utility. This entry will be retrieved from the configuration only if no discovery manager is specified in the constructor. Note that this object should not be shared with other components in the application that employs this utility. This item is used only by the service discovery manager, and not by any cache that is created. |
• | eventLeasePreparer |
  | Type: | {@link net.jini.security.ProxyPreparer} |
  | Default: | new {@link net.jini.security.BasicProxyPreparer}() |
  | Description: | Preparer for the leases returned when a cache registers with the event mechanism of any of the discovered lookup services. This item is used only by the caches (both internal and external) that are created by this utility, and not by the utility itself. Currently, no methods of the returned proxy are invoked by this utility. |
• | eventListenerExporter |
  | Type: | {@link net.jini.export.Exporter} |
  | Default: | new {@link net.jini.jeri.BasicJeriExporter#BasicJeriExporter(net.jini.jeri.ServerEndpoint,net.jini.jeri.InvocationLayerFactory,boolean,boolean) BasicJeriExporter}( {@link net.jini.jeri.tcp.TcpServerEndpoint#getInstance TcpServerEndpoint.getInstance}(0),                         new {@link net.jini.jeri.BasicILFactory}(),                         false, false) |
  | Description: | Exporter for the remote event listener that each cache supplies to the lookup services whose event mechanisms those caches register with. Note that for each cache that is created in this utility, a single, separate instance of this exporter will be retrieved and employed by that cache. Note also that the default exporter defined here will disable distributed garbage collection (DGC) for the server endpoint associated with the exported listener, and the listener backend (the "impl") will be strongly referenced. This means that the listener will not "go away" unintentionally. Additionally, that exporter also sets the keepAlive flag to false to allow the VM in which this utility runs to "go away" when desired; and not be kept alive simply because the listener is still exported. |
• | leaseManager |
  | Type: | {@link net.jini.lease.LeaseRenewalManager} |
  | Default: | new {@link net.jini.lease.LeaseRenewalManager#LeaseRenewalManager(net.jini.config.Configuration) LeaseRenewalManager}(config) |
  | Description: | The object used to manage any event leases returned to a cache that has registered with the event mechanism of the various discovered lookup services. This entry will be retrieved from the configuration only if no lease renewal manager is specified in the constructor. This item is used only by the caches (both internal and external) that are created by this utility, and not by the utility itself. |
• | registrarPreparer |
  | Type: | {@link net.jini.security.ProxyPreparer} |
  | Default: | new {@link net.jini.security.BasicProxyPreparer}() |
  | Description: | Preparer for the proxies to the lookup services that are discovered and used by this utility. This item is used only by the service discovery manager, and not by any cache that is created. The following methods of the proxy returned by this preparer are invoked by this utility: - {@link net.jini.core.lookup.ServiceRegistrar#lookup lookup}
- {@link net.jini.core.lookup.ServiceRegistrar#notify notify}
|
Logging
This implementation of
ServiceDiscoveryManager
uses the {@link Logger} named
net.jini.lookup.ServiceDiscoveryManager
to log information at the following logging levels:
net.jini.lookup.ServiceDiscoveryManager
Level | Description |
{@link java.util.logging.Level#INFO INFO} | when any exception occurs while querying a lookup service, or upon applying a filter to the results of such a query |
{@link java.util.logging.Level#INFO INFO} | when any exception occurs while attempting to register with the event mechanism of a lookup service, or while attempting to prepare the lease on the registration with that event mechanism |
{@link java.util.logging.Level#INFO INFO} | when any exception occurs while attempting to prepare a proxy |
{@link java.util.logging.Level#INFO INFO} | when an IllegalStateException occurs while discarding a lookup service proxy after logging a failure that has occurred in one of the tasks executed by this utility |
{@link java.util.logging.Level#INFO INFO} | upon failure of the lease renewal process |
{@link com.sun.jini.logging.Levels#HANDLED HANDLED} | when an exception occurs because a remote call to a lookup service has been interrupted as a result of the termination of a cache |
{@link com.sun.jini.logging.Levels#HANDLED HANDLED} | when a "gap" is encountered in an event sequence from a lookup service |
{@link java.util.logging.Level#FINER FINER} | upon failure of the lease cancellation process |
{@link java.util.logging.Level#FINEST FINEST} | whenever any task is started |
{@link java.util.logging.Level#FINEST FINEST} | whenever any task completes successfully |
{@link java.util.logging.Level#FINEST FINEST} | whenever a lookup cache is created |
{@link java.util.logging.Level#FINEST FINEST} | whenever a lookup cache is terminated |
{@link java.util.logging.Level#FINEST FINEST} | whenever a proxy is prepared |
{@link java.util.logging.Level#FINEST FINEST} | when an exception (that is, IllegalStateException ) occurs while unexporting a cache's remote event listener while the cache is being terminated |
See the {@link com.sun.jini.logging.LogManager} class for one way to usethe logging level {@link com.sun.jini.logging.Levels#HANDLED HANDLED} instandard logging configuration files.
@author Sun Microsystems, Inc.
@see net.jini.discovery.DiscoveryManagement
@see net.jini.lookup.LookupCache
@see net.jini.lookup.ServiceDiscoveryListener
@see net.jini.lookup.ServiceDiscoveryEvent
@see net.jini.core.lookup.ServiceRegistrar