You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by bu...@apache.org on 2010/12/16 17:10:04 UTC

svn commit: r780793 [10/17] - in /websites/staging/river/trunk/content/river/spec: ./ images/

Added: websites/staging/river/trunk/content/river/spec/lds-spec.html
==============================================================================
--- websites/staging/river/trunk/content/river/spec/lds-spec.html (added)
+++ websites/staging/river/trunk/content/river/spec/lds-spec.html Thu Dec 16 16:10:03 2010
@@ -0,0 +1,824 @@
+<!--
+ ! 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.
+ !-->
+
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<meta name="GENERATOR" content="Quadralay WebWorks Publisher 5.0.4">
+<link rel="StyleSheet" href="standard.css" type="text/css" media="screen">
+<title>Jini Lookup Discovery Service  </title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<a href="#skip" title="Skip navigation bar"></a>
+<table width="100%">
+<tr>
+<td align=left><a href="../../spec-index.html">Spec Index</a></td>
+<td align=right><em>A Collection of Jini Technology Helper Utilities and Services Specifications</em></td>
+</tr>
+</table>
+<br clear="all">
+
+
+<hr align="left">
+<table width="90%">
+<tr>
+<td align="right" font size="4"><b>Version 2.0</b></td>
+</tr>
+</table>
+<a name="skip"></a>
+<blockquote>
+<h2>
+  <a name="1013622"> </a>LD - Jini<font size="-1"><sup>TM</sup></font> Lookup Discovery Service</h2>
+<h3 class="Heading2">
+  <a name="1000045"> </a>LD.1	 Introduction
+</h3>
+<p class="Body">
+  <a name="1000634"> </a>Part of the <a href="discovery-spec.html"><em>Jini<font size="-1"><sup>TM</sup></font> Discovery and Join Specification</em></a> is devoted to defining the discovery requirements for well-behaved Jini clients and services, called <em class="Emphasis">discovering entities</em>, which are required to participate in the multicast discovery protocols. Discovering entities are required to send multicast discovery requests to lookup services with which the entities wish to interact. In addition, they must continuously listen for and act on announcements from the desired lookup services. Interactions with a discovered lookup service may involve registration with that lookup service, or may simply involve querying the lookup service for services of interest (or both). To find <em class="Emphasis">specific</em> lookup services, discovering entities also need to be able to participate in the unicast discovery protocol.
+</p>
+<p class="Body">
+  <a name="1002945"> </a>Under certain circumstances, a discovering entity may find it useful to allow a third party to perform the entity's discovery duties. For example, an activatable entity that wishes to deactivate may wish to employ a special Jini technology-enabled service (<em class="Emphasis">Jini service</em>)--referred to as a <em class="Emphasis">lookup discovery service</em>--to perform discovery duties on its behalf. Such an entity may wish to deactivate for various reasons, one being to conserve computational resources. While the entity is inactive, the lookup discovery service, running on the same or a separate host, would employ the discovery protocols to find lookup services in which the entity has expressed interest and would notify the entity when a previously unavailable lookup service has become available.
+</p>
+<p class="Body">
+  <a name="1003079"> </a>The facilities of the lookup discovery service are of particular value in a scenario in which a new lookup service is added to a long-lived djinn containing multiple inactive services. Without the use of a lookup discovery service, the time frame over which the new lookup service is fully populated can be both unpredictable and unbounded.
+</p>
+<p class="Body">
+  <a name="1015449"> </a>To understand why this time frame can be unpredictable, consider the fact that an inactive service has no way of discovering a new lookup service. This means that each inactive service in the djinn that wishes to discover and join a new lookup service must first activate. Since activation of a service occurs when some client attempts to use the service, the amount of time that passes between the arrival of the new lookup service and the activation of the service can vary greatly over the range of services in the djinn. Thus, the time frame over which the lookup service becomes fully populated cannot be predicted because it could take arbitrarily long before all of the services activate and then discover and join the new lookup service.
+</p>
+<p class="Body">
+  <a name="1003114"> </a>In addition to being unpredictable, the time it takes for the lookup service to fully populate can also be unbounded. This is because there is no guarantee that the lookup service will send multicast announcements between the time the service activates and the time it deactivates. If the timing is right, it is possible that one or more of the services in the djinn may never discover and join the new lookup service. Thus, without the use of the lookup discovery service, the new lookup service may never fully populate.
+</p>
+<p class="Body">
+  <a name="1002949"> </a>As another example of a discovering entity that may find it useful to allow a third party to perform the entity's discovery duties, consider an entity that exists in an environment with one of the following characteristics:
+</p>
+<ul>
+<p>
+  <li class="SmartList1"><a name="1002999"> </a>The environment does not support multicast.<p>
+  <li class="SmartList1"><a name="1003000"> </a>The environment contains no lookup services within the entity's <em class="Emphasis">multicast radius</em> (roughly, the number of hops beyond which neither the multicast requests from the entity nor the multicast announcements from the lookup service will propagate).<p>
+  <li class="SmartList1"><a name="1003001"> </a>The environment does contain lookup service(s) within the entity's multicast radius, but at least one service needed by the entity is not registered with any lookup service within that radius.
+</ul>
+
+<p class="Body">
+  <a name="1003002"> </a>If such an entity was provided with references to lookup services--located outside of the entity's multicast radius--that contain services needed by the entity, the entity could contact each lookup service and retrieve the desired service references. One way to provide the entity with access to those lookup services might be to configure the entity to find and use a lookup discovery service, operating beyond the entity's range, that can employ multicast discovery to find nearby lookup services belonging to groups in which the entity has expressed interest. After acquiring references to the targeted lookup services, the lookup discovery service would pass those references to the entity, providing the entity with access to the services registered with each lookup service. In this way, the entity participates in the multicast discovery protocols through a proxy relationship with the lookup discovery service, gaining access not only to lookup services ou
 tside of its own range, but also to all of the services registered with those lookup services.
+</p>
+<p class="Body">
+  <a name="1003028"> </a>Note that the scenario just described does not come without restrictions. For the lookup discovery service to be able to "link" an entity with lookup services in the way just described, the lookup discovery service must be registered with a lookup service having a location that either is known to the entity or is within the multicast radius of the entity. Furthermore, the lookup discovery service must be running on a host that is located within the multicast radius of the lookup services with which the entity wishes to be linked. That is, the entity must be able to find the lookup discovery service, and the lookup discovery service must be able to find the other desired lookup services.
+</p>
+<p class="Body">
+  <a name="1000724"> </a>To address these scenarios, the lookup discovery service participates in both the multicast discovery protocols and the unicast discovery protocol on behalf of a registered discovering entity or <em class="Emphasis">client</em>. This service will listen for and process multicast announcement packets from Jini lookup services and will, until successful, repeatedly attempt to discover specific lookup services that the client is interested in finding.
+</p>
+<p class="Body">
+  <a name="1000786"> </a>Upon discovery of a previously undiscovered lookup service of interest, the lookup discovery service notifies all entities that have requested the discovery of that lookup service that such an event has occurred. The event mechanism employed by the lookup discovery service satisfies the requirements defined in the <a href="event-spec.html"><em class="Emphasis">Jini Distributed Events Specification</em></a>. Note that the entity that receives such an event notification does not have to be the client of the lookup discovery service; it may be a third-party event-handling service such as an event mailbox service. Once a client is notified of the discovery of a lookup service, it is left to the client to define the semantics of how it interacts with that lookup service. For example, the client may wish to join the lookup service, simply query it for other useful services, or both.
+</p>
+<p class="Body">
+  <a name="1000236"> </a>The lookup discovery service must be implemented as a well-behaved Jini service and must comply with all of the policies embodied in the Jini technology programming model. Thus, the resources granted by this service are leased, and implementations of this service must adhere to the distributed leasing model for Jini technology as defined in the <a href="lease-spec.html"><em class="Emphasis">Jini Distributed Leasing Specification</em></a>. That is, the lookup discovery service will grant its services for only a limited period of time without an active expression of continuing interest on the part of the client.
+</p>
+<h4 class="Heading3">
+  <a name="1000358"> </a>LD.1.1	 Goals and Requirements
+</h4>
+<p class="Body">
+  <a name="1000359"> </a>The requirements of the interfaces and classes specified in this document are:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1002280"> </a>To define a service that not only employs the Jini discovery protocols to discover, by way of either group association or <code>LookupLocator</code> association, lookup services in which clients have registered interest, but that also notifies its clients of the discovery of those lookup services<p>
+  <li class="SmartList1"><a name="1000361"> </a>To provide this service in such a way that it can be used by entities that deactivate<p>
+  <li class="SmartList1"><a name="1000384"> </a>To comply with the policies of the Jini technology programming model
+</ul>
+
+<p class="Body">
+  <a name="1000385"> </a>The goals of this document are as follows:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1000364"> </a>To describe the lookup discovery service<p>
+  <li class="SmartList1"><a name="1000365"> </a>To provide guidance in the use and deployment of services that implement the <code>LookupDiscoveryService</code> interface and related classes and interfaces
+</ul>
+
+<h4 class="Heading3">
+  <a name="1000048"> </a>LD.1.2	 Other Types
+</h4>
+<p class="Body">
+  <a name="1000344"> </a>The types defined in the specification of the <code>LookupDiscoveryService</code> interface are in the <code>net.jini.discovery</code> package. The following object types may be referenced in this chapter. Whenever referenced, these object types will be referenced in unqualified form:
+</p>
+<pre  class="Preformatted">
+net.jini.core.discovery.LookupLocator
+net.jini.core.event.EventRegistration
+net.jini.core.event.RemoteEventListener
+net.jini.core.event.UnknownEventException
+net.jini.core.lease.Lease
+net.jini.core.lookup.ServiceID
+net.jini.core.lookup.ServiceRegistrar
+net.jini.discovery.DiscoveryEvent
+net.jini.discovery.DiscoveryGroupManagement
+net.jini.discovery.DiscoveryListener
+java.io.IOException
+java.rmi.MarshalledObject
+java.rmi.NoSuchObjectException
+java.rmi.RemoteException
+java.util.Map
+</pre>
+<h3 class="Heading2">
+  <a name="1000124"> </a>LD.2	 The Interface
+</h3>
+<p class="Body">
+  <a name="1000801"> </a>The <code>LookupDiscoveryService</code> interface defines the service--referred to as the <em class="Emphasis">lookup discovery service</em>--previously introduced in this specification. Through this interface, other Jini services and clients may request that discovery processing be performed on their behalf. This interface belongs to the <code>net.jini.discovery</code> package, and any service implementing this interface must comply with the definition of a Jini service. This interface is not a remote interface; each implementation of this service exports a front end proxy object that implements this interface local to the client, using an implementation-specific protocol to communicate with the actual remote server (the back end). All of the proxy methods must obey normal Java Remote Method Invocation (RMI) remote interface semantics except where explicitly noted. Two proxy objects are equal (using the <code>equals</code> method) if they are proxie
 s for the same lookup discovery service.
+</p>
+<p class="Body">
+  <a name="1005712"> </a>The one method defined in this interface throws a <code>RemoteException</code><code>, </code>and requires only the default serialization semantics so that this interface can be implemented directly using Java RMI.
+</p>
+<pre  class="Preformatted">
+package net.jini.discovery;
+
+public interface LookupDiscoveryService {
+    public LookupDiscoveryRegistration register(
+                              String[] groups,
+                              LookupLocator[] locators,
+                              RemoteEventListener listener,
+                              MarshalledObject handback,
+                              long leaseDuration)
+                                      throws RemoteException;
+}
+</pre>
+<p class="Body">
+  <a name="1003168"> </a>When requesting a registration with the lookup discovery service, the client indicates the lookup services it is interested in discovering by submitting two sets of objects. Each set may contain zero or more elements. One set consists of the names of the groups whose members are lookup services the client wishes to be discovered. The other set consists of <code>LookupLocator</code> objects, each corresponding to a specific lookup service the client wishes to be discovered.
+</p>
+<p class="Body">
+  <a name="1003183"> </a>For each successful registration the lookup discovery service will manage both the set of group names and the set of locators submitted. These sets will be referred to as the <em class="Emphasis">managed set of groups</em> and the <em class="Emphasis">managed set of locators</em>, respectively. The managed set of groups associated with a particular registration contains the names of the groups whose members consist of lookup services that the client wishes to be discovered through <em class="Emphasis">multicast</em> <em class="Emphasis">discovery</em>. Similarly, the managed set of locators contains instances of <code>LookupLocator</code>, each corresponding to a specific lookup service that the client wishes to be discovered through <em class="Emphasis">unicast</em> <em class="Emphasis">discovery</em>. The references to the lookup services that have been discovered will be maintained in a set referred to as the <em class="Emphasis">managed set of lo
 okup services</em> (or managed set of <em class="Emphasis">registrars</em>).
+</p>
+<p class="Body">
+  <a name="1015969"> </a>Note that when the general term <em class="Emphasis">managed set</em> is used, it should be clear from the context whether groups, locators, or registrars are being discussed. Furthermore, when the term <em class="Emphasis">group discovery</em> or <em class="Emphasis">locator discovery</em> is used, it should be taken to mean, respectively, the employment of either the multicast discovery protocols or the unicast discovery protocol to discover lookup services that correspond to members of the appropriate managed set.
+<p>
+Finally, with respect to any remote operation, two classes of exception are referenced in this document. The term <em>indefinite exception</em> refers to a class of exception where any such exception does not allow assertions to be made about the probability of success (or failure) of future attempts to perform the operation. A <code>RemoteException</code> caused by a transient communication failure is one such example of an exception that can be classified as an indefinite exception. As such, whenever an indefinite exception is encountered, retrying the operation at a later time may be advisable because the operation may succeed when retried.
+<p>
+The other class of exception to note is identified by the term <em>definite exception</em>, which refers to a class of exception where any such exception is indicative of a permanent failure. That is, when an operation fails as a result of an exception that can be classified as a definite exception, that exception allows one to assert that any future attempts to perform the failed operation will also be met with failure. In many cases, a <code>SecurityException</code> can be interpreted as a definite exception. Thus, whenever an operation fails as a result of a definite exception, because it is a virtual certainty that failure will again result on all future attempts to perform the operation, it is generally not advisable to retry the operation.
+
+</p>
+<h3 class="Heading2">
+  <a name="1000820"> </a>LD.3	 The Semantics
+</h3>
+<p class="Body">
+  <a name="1005549"> </a>To employ the lookup discovery service to perform discovery on its behalf, a client must first register with the lookup discovery service by invoking the <code>register</code> method defined in the <code>LookupDiscoveryService</code> interface. The <code>register</code> method is the only method specified by this interface.
+</p>
+<h4 class="Heading3">
+  <a name="1013657"> </a>LD.3.1	 Registration Semantics
+</h4>
+<p class="Body">
+  <a name="1003200"> </a>An invocation of the <code>register</code> method produces an object--referred to as a <code>registration object</code> (or simply a <code>registration</code>)--that is mutable. That is, the registration object contains methods through which it may be changed. Because registrations are mutable, each invocation of the <code>register</code> method produces a new registration object. Thus, the <code>register</code> method is not idempotent.
+</p>
+<p class="Body">
+  <a name="1005715"> </a>The <code>register</code> method may throw a <code>RemoteException</code>. Typically, this exception occurs when there is a communication failure between the client and the lookup discovery service. When this exception does occur, the registration may or may not have been successful.
+</p>
+<p class="Body">
+  <a name="1005542"> </a>Each registration with the lookup discovery service is persistent across restarts (or crashes) of the lookup discovery service until the lease on the registration expires or is cancelled.
+</p>
+<p class="Body">
+  <a name="1000950"> </a>The <code>register</code> method takes the following as arguments: 
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1015982"> </a>A <code>String</code> array, none of whose elements may be <code>null</code>, consisting of zero or more elements in which each element is the name of a group whose members are lookup services that the client requesting the registration wishes to be discovered via group discovery<p>
+  <li class="SmartList1"><a name="1015983"> </a>An array of <code>LookupLocator</code> objects, none of whose elements may be <code>null</code>, consisting of zero or more elements in which each element corresponds to a specific lookup service that the client requesting the registration wishes to be discovered via locator discovery<p>
+  <li class="SmartList1"><a name="1000887"> </a>A non-<code>null</code> <code>RemoteEventListener</code> object which specifies the entity that will receive events notifying the registration when a lookup service of interest is discovered or discarded<p>
+  <li class="SmartList1"><a name="1004704"> </a>Either <code>null</code> or an instance of <code>MarshalledObject</code> specifying an object that will be included in the notification event that the lookup discovery service sends to the registered listener<p>
+  <li class="SmartList1"><a name="1004705"> </a>A <code>long</code> value representing the amount of time (in milliseconds) for which the resources of the lookup discovery service are being requested
+</ul>
+
+<p class="Body">
+  <a name="1001052"> </a>The <code>register</code> method returns an object that implements the <code>LookupDiscoveryRegistration</code> interface. It is through this returned object that the client interacts with the lookup discovery service. This interaction includes activities such as group and locator management, state retrieval, and discarding discovered but unavailable lookup services so that they are eligible for rediscovery (see <a href="lds-spec.html#1000482">Section&nbsp;LD.4.1, "The LookupDiscoveryRegistration Interface"</a> for definition of the semantics of the methods of the <code>LookupDiscoveryRegistration</code> interface).
+</p>
+<p class="Body">
+  <a name="1016362"> </a>The <code>groups</code> argument takes a <code>String</code> array, none of whose elements may be <code>null</code>. Although it is acceptable to specify <code>null</code> (which is equivalent to <code>DiscoveryGroupManagement.ALL_GROUPS</code>) for the <code>groups</code> argument itself, if the argument contains one or more <code>null</code> elements, a <code>NullPointerException</code> is thrown. If the value is <code>null</code>, the lookup discovery service will attempt to discover all lookup services located within the multicast radius of the host on which the lookup discovery service is running. If an empty array (equivalent to <code>DiscoveryGroupManagement.NO_GROUPS</code>) is passed in, then no group discovery will be performed for the associated registration until the client, through the registration's <code>setGroups</code> or <code>addGroups</code> method, changes the contents of the managed set of groups to either a non-empty set of gro
 up names or <code>null</code>.
+</p>
+<p class="Body">
+  <a name="1006025"> </a>The <code>locators</code> argument takes an array of <code>LookupLocator</code> objects, none of whose elements may be <code>null</code>. If either the empty array or <code>null</code> is passed in as the <code>locators</code> argument, then no locator discovery will be performed for the associated registration until the client, through the registration's <code>addLocators</code> or <code>setLocators</code> method, changes the managed set of locators to a non-empty set of locators. Although it is acceptable to input <code>null</code> for the <code>locators</code> argument itself, if the argument contains one or more null elements, a <code>NullPointerException</code> is thrown.
+</p>
+<p class="Body">
+  <a name="1013740"> </a>If the <code>register</code> method is invoked with a set of group names and a set of locators in which either or both sets contain duplicate elements (where duplicate locators are determined by <code>LookupLocator.equals</code>), the invocation is equivalent to constructing this class with no duplicates in either set.
+</p>
+<p class="Body">
+  <a name="1005261"> </a>Upon discovery of a lookup service, through either group discovery or locator discovery, the lookup discovery service will send an event, referred to as a <em class="Emphasis">discovered event</em>, to the listener associated with the registration produced by the call to <code>register</code>.
+</p>
+<p class="Body">
+  <a name="1005265"> </a>After initial discovery of a lookup service, the lookup discovery service will continue to monitor the group membership state reflected in the multicast announcements from that lookup service. Depending on the lookup service's current group membership, the lookup discovery service may send either a discovered event or an event referred to as a <em class="Emphasis">discarded event</em>. The conditions under which either a discovered event or a discarded event will be sent are as follows:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1005275"> </a>If the multicast announcements from an already discovered lookup service indicate that the lookup service is a member of a new group, a discovered event will be sent to the listener of each registration that has yet to receive a discovered event for that lookup service, but that has previously registered interest in the new group.<p>
+  <li class="SmartList1"><a name="1005291"> </a>If the multicast announcements from an already discovered lookup service indicate that the lookup service has changed its group membership in such a way that the lookup service is no longer of interest to one or more of the registrations that previously registered interest in the groups of that lookup service, a discarded event will be sent to the listener of each such registration. This type of discarded event is sometimes referred to as a <em class="Emphasis">passive no-interest discarded event</em> ("passive" because the lookup discovery service, rather than the client, initiated the discard process).<p>
+  <li class="SmartList1"><a name="1005282"> </a>If the multicast announcements from an already discovered lookup service are no longer being received, a discarded event will be sent to the listener of each registration that previously registered interest in one or more of that lookup service's member groups. This type of discarded event is sometimes referred to as a <em class="Emphasis">passive communication discarded event</em>.
+</ul>
+
+<p class="Body">
+  <a name="1004757"> </a>It is important to note that when the lookup discovery service (passively) discards a lookup service, due to group membership changes (lost interest) or unavailability (communication failure), the discarded event will be sent to only the listeners of those registrations that have previously requested that the affected lookup service be discovered through at least group discovery. That is, the listener of any registration that is interested in the affected lookup service through <em class="Emphasis">only</em> locator discovery will not be sent either type of passive discarded event. This is because the semantics of the lookup discovery service assume that since the client, through the registration request, expressed no interest in discovering the lookup service through its group membership, the client must also have no interest in any group-related changes in that lookup service's state.
+</p>
+<p class="Body">
+  <a name="1016018"> </a>A more detailed discussion of the event semantics of the lookup discovery service is presented in <a href="lds-spec.html#1003321">Section&nbsp;LD.3.2, "Event Semantics"</a>.
+</p>
+<p class="Body">
+  <a name="1002730"> </a>A valid parameter must be passed as the <code>listener</code> argument of the <code>register</code> method. If a <code>null</code> value is input to this argument, then a <code>NullPointerException</code> will be thrown and the registration fails.
+</p>
+<p class="Body">
+  <a name="1015038"> </a>Note that if an indefinite exception occurs while attempting to send a discovered or discarded event to a registration's listener, the lookup discovery service will continue to attempt to send the event until either the event is successfully delivered or the client's lease on that registration expires. If an <code>UnknownEventException</code> or a definite exception occurs while attempting to send a discovered or discarded event to a registration's listener, the lookup discovery service assumes that the client is in an unknown, possibly corrupt state, and will cancel the lease on the registration and clear the registration from its managed set.
+</p>
+<p class="Body">
+  <a name="1003258"> </a>The state information maintained by the lookup discovery service includes the set of group names, locators, and listeners submitted by each client through each invocation of the <code>register</code> method, with duplicates eliminated. This state information contains no knowledge of the clients that register with the lookup discovery service. Thus, there is no requirement that a client identify itself during the registration process.
+</p>
+<h4 class="Heading3">
+  <a name="1003321"> </a>LD.3.2	 Event Semantics
+</h4>
+<p class="Body">
+  <a name="1004776"> </a>For each registration created by the lookup discovery service, an event identifier will be generated that uniquely maps the registration to the listener as well as to the registration's managed set of groups and managed set of locators. This event identifier is returned as a part of the returned registration object and is unique across all other active registrations with the lookup discovery service.
+</p>
+<p class="Body">
+  <a name="1006046"> </a>Whenever the lookup discovery service finds a lookup service matching the discovery criteria of one or more of its registrations, it sends an instance of <code>RemoteDiscoveryEvent</code> (a subclass of <code>RemoteEvent</code>) to the listener corresponding to each such registration. The event sent to each listener will contain the appropriate event identifier.
+</p>
+<p class="Body">
+  <a name="1016278"> </a>Once an event signaling the discovery (by group or locator) of a desired lookup service has been sent, no other discovered events for that lookup service will be sent to a registration's listener until the lookup service is discarded (either actively, by the client through the registration, or passively by the lookup discovery service) and then rediscovered. Note that more information about what it means for a lookup service to be discarded is presented in <a href="lds-spec.html#1013657">Section&nbsp;LD.3.1, "Registration Semantics"</a> and the section of this specification titled "<a href="lds-spec.html#1004325">Discarding Lookup Services</a>".
+</p>
+<p class="Body">
+  <a name="1016285"> </a>If, between the time a lookup service is discarded and the time it is rediscovered, a new registration is requested having parameters indicating interest in that lookup service, upon rediscovery of the lookup service an event will also be sent to that new registration's listener.
+</p>
+<p class="Body">
+  <a name="1016032"> </a>The sequence numbers for a given event identifier are strictly increasing (as defined in the <a href="event-spec.html"><em class="Emphasis">Jini Distributed Events Specification</em></a>), which means that when any two such successive events have sequence numbers that differ by only a value of 1, then no events have been missed. On the other hand, when the set of received events is viewed in order, if the difference between the sequence numbers of two successive events is greater than 1, then one or more events may or may not have been missed. For example, a difference greater than 1 could occur if the lookup discovery service crashes, even if no events are lost because of the crash. When two such successive events have sequence numbers whose difference is greater than 1, there is said to be a <em class="Emphasis">gap</em> between the events.
+</p>
+<p class="Body">
+  <a name="1005149"> </a>When a gap occurs between events, the local state (on the client) related to the discovered lookup services may or may not fall out of sync with the corresponding remote state maintained by the lookup discovery service. For example, if the gap corresponds to a missed event representing the (initial) discovery of a targeted lookup service, the remote state will reflect this discovery, whereas the client's local state will not. To allow clients to identify and correct such a situation, each registration object provides a method that returns a set consisting of the proxies to the lookup services that have been discovered for that registration. With this information the client can update its local state.
+</p>
+<p class="Body">
+  <a name="1006050"> </a>When requesting a registration with the lookup discovery service, a client may also supply (as a parameter to the <code>register</code> method) a reference to an object, wrapped in a <code>MarshalledObject</code>, referred to as a <em class="Emphasis">handback</em>. When the lookup discovery service sends an event to a registration's listener, the event will also contain a reference to this handback object. The lookup discovery service will not change the handback object. That is, the handback object contained in the event sent by the lookup discovery service will be identical to the handback object registered by the client with the event mechanism.
+</p>
+<p class="Body">
+  <a name="1010251"> </a>The semantics of the object input to the <code>handback</code> argument are left to each client to define, although <code>null</code> may be input to this argument. The role of the <code>handback</code> object in the remote event mechanism is detailed in the <a href="event-spec.html"><em class="Emphasis">Jini Distributed Events Specification</em></a>.
+</p>
+<h4 class="Heading3">
+  <a name="1003330"> </a>LD.3.3	 Leasing Semantics
+</h4>
+<p class="Body">
+  <a name="1001075"> </a>When a client registers with the lookup discovery service, it is effectively requesting a lease on the resources provided by that service. The initial duration of the lease granted to a client by the lookup discovery service will be less than or equal to the requested duration reflected in the value input to the <code>leaseDuration</code> argument. That value must be positive, <code>Lease.FOREVER</code>, or <code>Lease.ANY</code>. If any other value is input to this argument, an <code>IllegalArgumentException</code> will be thrown. The client may obtain a reference to the <code>Lease</code> object granted by the lookup discovery service through the associated registration returned by the service (see <a href="lds-spec.html#1000482">Section&nbsp;LD.4.1, "The LookupDiscoveryRegistration Interface"</a>).
+</p>
+<h3 class="Heading2">
+  <a name="1000518"> </a>LD.4	 Supporting Interfaces and Classes
+</h3>
+<p class="Body">
+  <a name="1013938"> </a>The lookup discovery service depends on the <code>LookupDiscoveryRegistration</code> interface, as well as on the concrete classes <code>RemoteDiscoveryEvent</code> and <code>LookupUnmarshalException</code>.
+</p>
+<h4 class="Heading3">
+  <a name="1000482"> </a>LD.4.1	 The <code>LookupDiscoveryRegistration</code> Interface
+</h4>
+<p class="Body">
+  <a name="1000483"> </a>When a client requests a registration with the lookup discovery service, an object that implements the <code>LookupDiscoveryRegistration</code> interface is returned. It is through this interface that the client manages the state of its registration with the lookup discovery service.
+</p>
+<pre  class="Preformatted">
+package net.jini.discovery;
+
+public interface LookupDiscoveryRegistration {
+    public EventRegistration getEventRegistration();
+    public Lease getLease();
+    public ServiceRegistrar[] getRegistrars()
+                             throws LookupUnmarshalException,
+                                    RemoteException;
+    public String[] getGroups() throws RemoteException;
+    public LookupLocator[] getLocators()
+                                      throws RemoteException;
+    public void addGroups(String[] groups)
+                                      throws RemoteException;
+    public void setGroups(String[] groups)
+                                      throws RemoteException;
+    public void removeGroups(String[] groups)
+                                      throws RemoteException;
+    public void addLocators(LookupLocator[] locators)
+                                      throws RemoteException;
+    public void setLocators(LookupLocator[] locators)
+                                      throws RemoteException;
+    public void removeLocators(LookupLocator[] locators)
+                                      throws RemoteException;
+    public void discard(ServiceRegistrar registrar)
+                                      throws RemoteException;
+}
+</pre>
+<p class="Body">
+  <a name="1016084"> </a>As with the <code>LookupDiscoveryService</code> interface, the <code>LookupDiscoveryRegistration</code> interface is not a remote interface. Each implementation of the lookup discovery service exports proxy objects that implement this interface local to the client, using an implementation-specific protocol to communicate with the actual remote server. All of the proxy methods must obey normal Java RMI remote interface semantics except where explicitly noted. Two proxy objects are equal (using the <code>equals</code> method) if they are proxies for the same registration created by the same lookup discovery service.
+</p>
+<p class="Body">
+  <a name="1016088"> </a>The discovery facility of the lookup discovery service, together with its event mechanism, make up the set of resources clients register to use. Because the resources of the lookup discovery service are leased, access is granted for only a limited period of time unless there is an active expression of continuing interest on the part of the client. 
+</p>
+<p class="Body">
+  <a name="1003453"> </a>When a client uses the registration process to request that a lookup discovery service perform discovery of a set of desired lookup services, the client is also registered with the service's event mechanism. Because of this implicit registration with the event mechanism, the lookup discovery service "bundles" both resources under a single lease. When that lease expires, both discovery processing and event notifications will cease with respect to the registration that resulted from the client's request.
+</p>
+<p class="Body">
+  <a name="1016411"> </a>To facilitate lease management and event handling, the <code>LookupDiscoveryRegistration</code> interface defines methods that allow the client to retrieve its event registration information. Additional methods defined by this interface allow the client to retrieve references to the registration's currently discovered lookup services, as well as to modify the managed sets of groups and locators.
+</p>
+<p class="Body">
+  <a name="1016098"> </a>If the client's registration with the lookup discovery service has expired or been cancelled, then any invocation of a remote method defined in this interface will result in a <code>NoSuchObjectException</code>. That is, any method that communicates with the back-end server of the lookup discovery service will throw a <code>NoSuchObjectException</code> if the registration on which the method is invoked no longer exists. Note that if a client receives a <code>NoSuchObjectException</code> as a result of an invocation of such a method, although the client can assume that the registration no longer exists, the client cannot assume that the lookup discovery service itself no longer exists.
+</p>
+<p class="Body">
+  <a name="1005764"> </a>Each remote method of this interface may throw a <code>RemoteException</code>. Typically, this exception occurs when there is a communication failure between the client and the lookup discovery service. Whenever this exception occurs as a result of the invocation of one of these methods, the method may or may not have completed its processing successfully.
+</p>
+<h5 class="Heading4">
+  <a name="1001142"> </a>LD.4.1.1	 The Semantics
+</h5>
+<p class="Body">
+  <a name="1003498"> </a>The methods defined by this interface are organized into a set of accessor methods, a set of group mutator methods, a set of locator mutator methods, and the <code>discard</code> method. Through the accessor methods, various elements of a registration's state can be retrieved. The mutator methods provide a mechanism for changing the set of groups and locators to be discovered for the registration. Through the <code>discard</code> method, a particular lookup service may be made eligible for rediscovery.
+</p>
+<div style="color: #000000; font-family: Times; font-size: 11pt; font-style: normal; font-weight: bold; margin-bottom: 8pt; margin-left: 36pt; margin-right: 0pt; margin-top: 13pt; text-align: left; text-decoration: none; text-indent: -36pt; text-transform: none; vertical-align: baseline">
+<a name="1003503"> </a>The Accessor Methods<br>
+</div>
+<p class="Body">
+  <a name="1003502"> </a>The <code>getEventRegistration</code> method returns an <code>EventRegistration</code> object that encapsulates the information the client needs to identify a notification sent by the lookup discovery service to the registration's listener. This method is not remote and takes no arguments.
+</p>
+<p class="Body">
+  <a name="1005172"> </a>The <code>getLease</code> method returns the <code>Lease</code> object that controls a client's registration with the lookup discovery service. It is through the <code>Lease</code> object returned by this method that the client requests the renewal or cancellation of the registration with the lookup discovery service. This method is not remote and takes no arguments.
+</p>
+<p class="Body">
+  <a name="1005170"> </a>Note that the object returned by the <code>getEventRegistration</code> method also provides a <code>getLease</code> method. That method and the <code>getLease</code> method defined by the <code>LookupDiscoveryRegistration</code> interface both return the same <code>Lease</code> object. The <code>getLease</code> method defined here is provided as a convenience to avoid the indirection associated with the <code>getLease</code> method on the <code>EventRegistration</code> object, as well as to avoid the overhead of making two method calls.
+</p>
+<p class="Body">
+  <a name="1009440"> </a>The <code>getRegistrars</code> method returns a set of instances of the <code>ServiceRegistrar</code> interface. Each element in the set is a proxy to one of the lookup services that have already been discovered for the registration. Additionally, each element in the set will be unique with respect to all other elements in the set, as determined by the <code>equals</code> method provided by each element. The contents of the set make up the current remote state of the set of lookup services discovered for the registration. This method returns a new array on each invocation.
+</p>
+<p class="Body">
+  <a name="1009460"> </a>This method can be used to maintain synchronization between the set of discovered lookup services making up a registration's local state on the client and the registration's corresponding remote state maintained by the lookup discovery service. The local state can become unsynchronized with the remote state when a gap occurs in the events received by the registration's listener.
+</p>
+<p class="Body">
+  <a name="1005218"> </a>According to the event semantics of the lookup discovery service, if there is no gap between two sequence numbers, no events have been missed and the states remain synchronized with each other; if there is a gap, events may or may not have been missed. Therefore, upon finding gaps in the sequence of events, the client can invoke this method and use the returned information to synchronize the local state with the remote state.
+</p>
+<p class="Body">
+  <a name="1009483"> </a>To construct its return set, the <code>getRegistrars</code> method retrieves from the lookup discovery service the set of lookup service proxies making up the registration's current remote state. When the lookup discovery service sends the requested set of proxies, the set is sent as a set of marshalled instances of the <code>ServiceRegistrar</code> interface. The lookup discovery service individually marshals each proxy in the set that it sends because if it were not to do so, <em class="Emphasis">any</em> deserialization failure on the set would result in an <code>IOException</code>, and failure would be declared for the whole deserialization process, not just an individual element. This would mean that all elements of the set sent by the lookup discovery service--even those that were successfully deserialized--would be unavailable to the client. Individually marshalling each element in the set minimizes the "all or nothing" aspect of the deseriali
 zation process, allowing the client to recover those proxies that can be successfully unmarshalled and to proceed with processing that might not be possible otherwise.
+</p>
+<p class="Body">
+  <a name="1009546"> </a>When constructing the return set, this method attempts to unmarshal each element of the set of marshalled proxy objects sent by the lookup discovery service. When failure occurs while attempting to unmarshal any of those elements, this method throws an exception of type <code>LookupUnmarshalException</code> (described later). It is through the contents of that exception that the client can recover any available proxies and perform error handling related to the unavailable proxies. The contents of the <code>LookupUnmarshalException</code> provide the client with the following useful information: 
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1009515"> </a>The knowledge that a problem has occurred while unmarshalling at least one of the elements making up the remote state of the registration's discovered lookup services<p>
+  <li class="SmartList1"><a name="1009525"> </a>The set of proxy objects that were successfully unmarshalled by the <code>getRegistrars</code> method<p>
+  <li class="SmartList1"><a name="1009526"> </a>The set of marshalled proxy objects that could not be unmarshalled by the <code>getRegistrars</code> method<p>
+  <li class="SmartList1"><a name="1009516"> </a>The set of exceptions corresponding to each failed attempt at unmarshalling<p>
+</ul>
+
+<p class="Body">
+  <a name="1009608"> </a>The type of exception that occurs when attempting to unmarshal an element of the set sent by the lookup discovery service is typically an <code>IOException</code> or a <code>ClassNotFoundException</code> (usually the more common of the two). A <code>ClassNotFoundException</code> occurs whenever a remote object on which the marshalled proxy depends cannot be retrieved and loaded, usually because the codebase of one of the object's classes or interfaces is currently "down." To address this situation, the client may wish to proceed with its processing using the successfully unmarshalled proxies, and attempt to unmarshal the unavailable proxies (or re-invoke this method) at some later time.
+</p>
+<p class="Body">
+  <a name="1009609"> </a>If the <code>getRegistrars</code> method returns successfully without throwing a <code>LookupUnmarshalException</code>, the client is guaranteed that all marshalled proxies belonging to the set sent by the lookup discovery service have each been successfully unmarshalled; the client then has a snapshot--relative to the point in time when this method is invoked--of the remote state of the lookup services discovered for the associated registration.
+</p>
+<p class="Body">
+  <a name="1010509"> </a>The <code>getGroups</code> method returns an array consisting of the group names from the registration's managed set; that is, the names of the groups the lookup discovery service is currently configured to discover for the associated registration. If the managed set of groups is empty, this method returns the empty array. If there is no managed set of groups associated with the registration (that is, the lookup discovery service is configured to discover <code>DiscoveryGroupManagement.ALL_GROUPS</code> for the registration), then <code>null</code> is returned.
+</p>
+<p class="Body">
+  <a name="1003572"> </a>The <code>getLocators</code> method returns an array consisting of the <code>LookupLocator</code> objects from the registration's managed set; that is, the locators of the specific lookup services the lookup discovery service is currently configured to discover for the associated registration. If the managed set of locators is empty, this method returns the empty array.
+</p>
+<div style="color: #000000; font-family: Times; font-size: 11pt; font-style: normal; font-weight: bold; margin-bottom: 8pt; margin-left: 36pt; margin-right: 0pt; margin-top: 13pt; text-align: left; text-decoration: none; text-indent: -36pt; text-transform: none; vertical-align: baseline">
+<a name="1003493"> </a>The Group Mutator Methods<br>
+</div>
+<p class="Body">
+  <a name="1016114"> </a>With respect to a particular registration, the groups to be discovered may be modified using the methods described in this section. In each case, a set of groups is represented as a <code>String</code> array, none of whose elements may be <code>null</code>. If any set of groups input to one of these methods contains one or more null elements, a <code>NullPointerException</code> is thrown. The empty set is denoted by the empty array (<code>DiscoveryGroupManagement.NO_GROUPS</code>), and "no set" is indicated by <code>null</code> (<code>DiscoveryGroupManagement.ALL_GROUPS</code>). No set indicates that all lookup services within the multicast radius should be discovered, regardless of group membership. Invoking any of these methods with an input set of groups that contains duplicate names is equivalent to performing the invocation with the duplicate group names removed from the input set.
+</p>
+<p class="Body">
+  <a name="1003622"> </a>The <code>addGroups</code> method adds a set of group names to the registration's managed set. This method takes one argument: a <code>String</code> array consisting of the set of group names with which to augment the registration's managed set.
+</p>
+<p class="Body">
+  <a name="1015481"> </a>If the registration has no current managed set of groups to augment, this method throws an <code>UnsupportedOperationException</code>. If the parameter value is <code>null</code>, this method throws a <code>NullPointerException</code>. If the parameter value is the empty array, then the registration's managed set of groups will not change.
+</p>
+<p class="Body">
+  <a name="1001577"> </a>The <code>setGroups</code> method replaces all of the group names in the registration's managed set with names from a new set. This method takes one argument: a <code>String</code> array consisting of the set of group names with which to replace the current names in the registration's managed set.
+</p>
+<p class="Body">
+  <a name="1002847"> </a>If <code>null</code> is passed to <code>setGroups</code>, the lookup discovery service will attempt to discover any undiscovered lookup services located within range of the lookup discovery service, regardless of group membership.
+</p>
+<p class="Body">
+  <a name="1015117"> </a>If the empty set is passed to <code>setGroups</code>, then group discovery will be halted until the registration's managed set of groups is changed--through a subsequent call to this method or to <code>addGroups</code>--to a set that is either a non-empty set of group names or <code>null</code>.
+</p>
+<p class="Body">
+  <a name="1015119"> </a>The <code>removeGroups</code> method deletes a set of group names from the registration's managed set. This method takes one argument: a <code>String</code> array containing the set of group names to remove from the registration's managed set.
+</p>
+<p class="Body">
+  <a name="1004966"> </a>If the registration has no current managed set of groups from which to remove elements, this method throws an <code>UnsupportedOperationException</code>. If <code>null</code> is input, this method throws a <code>NullPointerException</code>. If the registration does have a managed set of groups from which to remove elements, but either the input set is empty or none of the elements in the input set match any element in the managed set, then the registration's managed set of groups will not change.
+</p>
+<p class="Body">
+  <a name="1014098"> </a>Once a new group name has been placed in the registration's managed set as a result of an invocation of either <code>addGroups</code> or <code>setGroups</code>, if there are lookup services belonging to that group that have already been discovered for that registration, no event will be sent to the registration's listener for those particular lookup services. However, attempts to discover any undiscovered lookup services belonging to that group will continue to be made on behalf of the registration.
+</p>
+<p class="Body">
+  <a name="1014099"> </a>Any already discovered lookup service that is a member of one or more of the groups removed from the registration's managed set as a result of an invocation of either <code>setGroups</code> or <code>removeGroups</code> will be discarded and will no longer be eligible for discovery (for that registration), but only if that lookup service satisfies both of the following conditions:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1014069"> </a>The lookup service is not a member of any group in the registration's new managed set resulting from the invocation of <code>setGroups</code> or <code>removeGroups</code><p>
+  <li class="SmartList1"><a name="1014071"> </a>With respect to the registration, the lookup service is not currently eligible for discovery through locator discovery; that is, the lookup service does not correspond to any element in the registration's managed set of locators.
+</ul>
+
+<div style="color: #000000; font-family: Times; font-size: 11pt; font-style: normal; font-weight: bold; margin-bottom: 8pt; margin-left: 36pt; margin-right: 0pt; margin-top: 13pt; text-align: left; text-decoration: none; text-indent: -36pt; text-transform: none; vertical-align: baseline">
+<a name="1004970"> </a>The Locator Mutator Methods<br>
+</div>
+<p class="Body">
+  <a name="1006131"> </a>With respect to a particular registration, the set of locators to discover may be modified using the methods described in this section. In each case, a set of locators is represented as an array of <code>LookupLocator</code> objects, none of whose elements may be <code>null</code>. If any set of locators input to one of these methods contains one of more null elements, a <code>NullPointerException</code> is thrown. Invoking any of these methods with a set of locators that contains duplicate locators (as determined by <code>LookupLocator.equals</code>) is equivalent to performing the invocation with the duplicates removed from the input set.
+</p>
+<p class="Body">
+  <a name="1003802"> </a>The <code>addLocators</code> method adds a set of <code>LookupLocator</code> objects to the registration's managed set. This method takes one argument: an array consisting of the set of locators with which to augment the registration's managed set.
+</p>
+<p class="Body">
+  <a name="1004241"> </a>If <code>null</code> is passed to <code>addLocators</code>, a <code>NullPointerException</code> will be thrown. If the parameter value is the empty array, the registration's managed set of locators will not change.
+</p>
+<p class="Body">
+  <a name="1016425"> </a>The <code>setLocators</code> method replaces all of the locators in the registration's managed set with <code>LookupLocator</code> objects from a new set. This method takes one argument: an array consisting of the set of locators with which to replace the current locators in the registration's managed set.
+</p>
+<p class="Body">
+  <a name="1016426"> </a>If <code>null</code> is passed to <code>setLocators</code>, a <code>NullPointerException</code> will be thrown.
+</p>
+<p class="Body">
+  <a name="1016427"> </a>If the empty set is passed to <code>setLocators</code>, then locator discovery will be halted until the registration's managed set of locators is changed--through a subsequent call to this method or to <code>addLocators</code>--to a set that is non-<code>null</code> and non-empty.
+</p>
+<p class="Body">
+  <a name="1016428"> </a>The <code>removeLocators</code> method deletes a set of <code>LookupLocator</code> objects from the registration's managed set. This method takes one argument: an array containing the set of <code>LookupLocator</code> objects to remove from the registration's managed set.
+</p>
+<p class="Body">
+  <a name="1016429"> </a>If <code>null</code> is passed to <code>removeLocators</code>, a <code>NullPointerException</code> will be thrown. If any element of the set of locators to remove is not contained in the registration's managed set, <code>removeLocators</code> takes no action with respect to that element. If the parameter value is the empty array, the managed set of locators will not change.
+</p>
+<p class="Body">
+  <a name="1005899"> </a>Whenever a new locator is placed in the managed set as a result of an invocation of one of the locator mutator methods and that new locator equals none of the previously discovered locators (across all registrations), the lookup discovery service will attempt unicast discovery of the lookup service associated with the new locator.
+</p>
+<p class="Body">
+  <a name="1004223"> </a>If locator discovery is attempted for a registration, such discovery attempts will be repeated until one of the following events occurs:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1004224"> </a>The lookup service is discovered<p>
+  <li class="SmartList1"><a name="1004225"> </a>The client's lease on the registration expires<p>
+  <li class="SmartList1"><a name="1004226"> </a>The client explicitly removes the locator from the registration's managed set
+</ul>
+
+<p class="Body">
+  <a name="1004227"> </a>Upon discovery of the lookup service corresponding to the new locator, or upon finding a match between the new locator and a previously discovered lookup service, a discovered event will be sent to the registration's listener, unless that lookup service was previously discovered for that registration through group discovery.
+</p>
+<p class="Body">
+  <a name="1014188"> </a>Any already discovered lookup service corresponding to a locator that is removed from the registration's managed set as a result of an invocation of either <code>setLocators</code> or <code>removeLocators</code> will be discarded and will no longer be eligible for discovery, but only if it is not currently eligible for discovery through group discovery--that is, only if the lookup service is not also a member of one or more of the groups in the registration's managed set of groups.
+</p>
+<div style="color: #000000; font-family: Times; font-size: 11pt; font-style: normal; font-weight: bold; margin-bottom: 8pt; margin-left: 36pt; margin-right: 0pt; margin-top: 13pt; text-align: left; text-decoration: none; text-indent: -36pt; text-transform: none; vertical-align: baseline">
+<a name="1004325"> </a>Discarding Lookup Services<br>
+</div> 
+<p class="Body">
+  <a name="1004333"> </a>When the lookup discovery service removes an already discovered lookup service from a registration's managed set of lookup services, the lookup service is said to be <em class="Emphasis">discarded</em>.
+</p>
+<p class="Body">
+  <a name="1005344"> </a>There are a number of situations in which the lookup discovery service will discard a lookup service:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1005347"> </a>In response to a discard request resulting from an invocation of a registration's <code>discard</code> method<p>
+  <li class="SmartList1"><a name="1014276"> </a>In response to a declaration--via an invocation of one of the mutator methods on a registration--that there is no longer any interest in one or more of the registration's already discovered lookup services<p>
+  <li class="SmartList1"><a name="1014254"> </a>In response to the determination that the multicast announcements from an already discovered lookup service indicate that the lookup service has changed its group membership in such a way that the lookup service is no longer of interest to one or more of the registrations that previously registered interest in the groups of that lookup service<p>
+  <li class="SmartList1"><a name="1014287"> </a>In response to the determination that the multicast announcements from an already discovered lookup service are no longer being received
+</ul>
+
+<p class="Body">
+  <a name="1014210"> </a>For each of these cases, whenever the lookup discovery service discards a lookup service, it will send an event to the registration's listener to notify it that the lookup service has been discarded.
+</p>
+<p class="Body">
+  <a name="1004599"> </a>The <code>discard</code> method provides a mechanism for registered clients to inform the lookup discovery service of the existence of an unavailable--or <em class="Emphasis">unreachable</em>--lookup service, and to request that the lookup discovery service discard that lookup service and make it eligible for rediscovery.
+</p>
+<p class="Body">
+  <a name="1002366"> </a>The <code>discard</code> method takes a single argument: the proxy to the lookup service to discard. This method takes no action if the parameter to this method equals none of the proxies reflected in the managed set (using proxy equality as defined in the <a href="lookup-spec.html"><em class="Emphasis">Jini Lookup Service Specification</em></a>. If <code>null</code> is passed to <code>discard</code>, a <code>NullPointerException</code> is thrown.
+</p>
+<p class="Body">
+  <a name="1015507"> </a>Although the lookup discovery service monitors the multicast announcements from all discovered lookup services for indications of unavailability, it should be noted that there are conditions under which the lookup discovery service will not discard such a lookup service, even when the lookup service is found to be unreachable. Whether or not the lookup discovery service discards such an unreachable lookup service is dependent on how each registration is configured for discovery with respect to that lookup service. If every registration that is configured to discover the unreachable lookup service is configured to discover it through locator discovery only, the lookup discovery service will not discard the lookup service. In other words, in order for the lookup discovery service to discard a lookup service it has determined is unreachable, at least one registration must be configured for discovery of at least one group in which that lookup service is 
 a member.
+</p>
+<p class="Body">
+  <a name="1014334"> </a>Thus, whenever a client determines that a previously discovered lookup service has become unreachable, it should not rely on the lookup discovery service to discard the lookup service. Instead, the client should inform the lookup discovery service--through the invocation of the registration's <code>discard</code> method--that the previously discovered lookup service is no longer available and that attempts should be made to rediscover that lookup service for the registration. Typically, a client determines that a lookup service is unavailable when the client attempts to use the lookup service but receives an exception (indefinite or definite) as a result of the attempt.
+</p>
+<p class="Body">
+  <a name="1015995"> </a>Note that the lookup discovery service may be acting on behalf of numerous clients that have access to the same lookup service. If that lookup service becomes unavailable, many of those clients may invoke <code>discard</code> between the time the lookup service becomes unavailable and the time it is rediscovered. Upon the first invocation of <code>discard</code>, the lookup discovery service will re-initiate discovery of the relevant lookup service for the registration of the client that made the invocation. For all other invocations made prior to rediscovery, the registrations through which the invocation is made are sent a discarded event, and added to the list of registrations that will be notified when rediscovery of the lookup service does occur. That is, upon rediscovery of the lookup service, only those registrations through which the <code>discard</code> method was invoked will be notified.
+</p>
+<p class="Body">
+  <a name="1010785"> </a>Upon successful completion of the <code>discard</code> method, the proxy requested to be discarded is guaranteed to have been removed from the managed set of the registration through which the invocation was made. No such guarantee is made with respect to when the discarded event is sent to each such registration's listener. That is, the event notifying the listeners that the lookup service has been discarded may or may not be sent asynchronously.
+</p>
+<h4 class="Heading3">
+  <a name="1009648"> </a>LD.4.2	 The <code>RemoteDiscoveryEvent</code> Class
+</h4>
+<p class="Body">
+  <a name="1009649"> </a>When the lookup discovery service discovers or discards a lookup service matching the criteria established through one of its registrations, the lookup discovery service sends an instance of the <code>RemoteDiscoveryEvent</code> class to the <code>RemoteEventListener</code> implemented by the client and registered with the lookup discovery service.
+</p>
+<pre  class="Preformatted">
+package net.jini.discovery;
+
+public class RemoteDiscoveryEvent extends RemoteEvent {
+    public RemoteDiscoveryEvent(Object source,
+                                long eventID,
+                                long seqNum, 
+                                MarshalledObject handback,
+                                boolean discarded,
+                                Map groups)
+                                       throws IOException {...}
+
+    public boolean isDiscarded() {...}
+    public ServiceRegistrar[] getRegistrars()
+                          throws LookupUnmarshalException {...}
+    public Map getGroups() {...}
+}
+</pre>
+<p class="Body">
+  <a name="1014449"> </a>The <code>RemoteDiscoveryEvent</code> class provides an encapsulation of event information that the lookup discovery service uses to notify a registration of the occurrence of an event involving one or more <code>ServiceRegistrar</code> objects (lookup services) in which the registration has registered interest. The lookup discovery service passes an instance of this class to the registration's discovery listener when one of the following events occurs:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1014450"> </a>Each lookup service referenced in the event has been discovered for the first time or rediscovered after having been discarded.<p>
+  <li class="SmartList1"><a name="1014452"> </a>Each lookup service referenced in the event has been either actively or passively discarded.
+</ul>
+
+<p class="Body">
+  <a name="1009654"> </a><code>RemoteDiscoveryEvent</code> is a subclass of <code>RemoteEvent</code>, adding the following additional items of abstract state: 
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1014400"> </a>A <code>boolean</code> indicating whether the lookup services referenced by the event have been discovered or discarded<p>
+  <li class="SmartList1"><a name="1014401"> </a>A set of marshalled instances of the <code>ServiceRegistrar</code> interface having the characteristic that when each element is unmarshalled, the result is a proxy to one of the discovered or discarded lookup services referenced by the event<p>
+  <li class="SmartList1"><a name="1014402"> </a>A <code>Map</code> instance in which the elements of the map's key set are the instances of <code>ServiceID</code> that correspond to each lookup service reference returned in the event, and the map's value set contains the corresponding member groups of each lookup service reference
+</ul>
+
+<p class="Body">
+  <a name="1014398"> </a>Methods are defined through which this additional state may be retrieved upon receipt of an instance of this class.
+</p>
+<p class="Body">
+  <a name="1004848"> </a>Clients need to know not only when a targeted lookup service has been discovered, but also when it has been discarded. The lookup discovery service uses an instance of <code>RemoteDiscoveryEvent</code> to notify a registration when either of these events occurs, as indicated by the value of the <code>boolean</code> state variable. When the value of that variable is <code>true</code>, the event is referred to as a <em class="Emphasis">discarded event</em>; when <code>false</code>, it is referred to as a <em class="Emphasis">discovered event</em>.
+</p>
+<h5 class="Heading4">
+  <a name="1004849"> </a>LD.4.2.1	 The Semantics
+</h5>
+<p class="Body">
+  <a name="1005022"> </a>The constructor of the <code>RemoteDiscoveryEvent</code> class takes the following parameters as input:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1009333"> </a>A reference to the lookup discovery service that generated the event<p>
+  <li class="SmartList1"><a name="1009338"> </a>The event identifier that maps a particular registration to both its listener and its targeted groups and locators<p>
+  <li class="SmartList1"><a name="1009339"> </a>The sequence number of the event being constructed<p>
+  <li class="SmartList1"><a name="1009340"> </a>The client-defined handback (which may be <code>null</code>)<p>
+  <li class="SmartList1"><a name="1009662"> </a>A flag indicating whether the event being constructed is a discovered event or a discarded event<p>
+  <li class="SmartList1"><a name="1016141"> </a>A <code>Map</code> whose key set contains the proxies to newly discovered or discarded lookup service(s) the event is to reference, and whose value set contains the corresponding member groups of each lookup service
+</ul>
+
+<p class="Body">
+  <a name="1016142"> </a>If the <code>groups</code> parameter is empty, the constructor will throw an <code>IllegalArgumentException</code>. If null is input to the <code>groups</code> parameter, the constructor will throw a <code>NullPointerException</code>. If none of the proxies referenced in the <code>groups</code> parameter can be successfully serialized, the constructor will throw an <code>IOException</code>.
+</p>
+<p class="Body">
+  <a name="1009331"> </a>The <code>isDiscarded</code> method returns a <code>boolean</code> that indicates whether the event is a discovered event or a discarded event. If the event is a discovered event, then this method returns <code>false</code>. If the event is a discarded event, <code>true</code> is returned.
+</p>
+<p class="Body">
+  <a name="1016149"> </a>The <code>getRegistrars</code> method returns an array consisting of instances of the <code>ServiceRegistrar</code> interface. Each element in the returned set is a proxy to one of the newly discovered or discarded lookup services that caused a <code>RemoteDiscoveryEvent</code> to be sent. Additionally, each element in the returned set will be unique with respect to all other elements in the set, as determined by the equals method provided by each element. This method does not make a remote call. With respect to multiple invocations of this method, each invocation will return a new array.
+</p>
+<p class="Body">
+  <a name="1009722"> </a>When the lookup discovery service sends an instance of <code>RemoteDiscoveryEvent</code> to the listener of a client's registration, the set of lookup service proxies contained in the event consists of marshalled instances of the <code>ServiceRegistrar</code> interface. The lookup discovery service individually marshals each proxy associated with the event because if it were not to do so, <em class="Emphasis">any</em> deserialization failure on the set would result in an <code>IOException</code>, and failure would be declared for the whole deserialization process, not just an individual element. This would mean that all elements of the set sent in the event--even those that can be successfully deserialized--would be unavailable to the client through this method. Just as with the <code>getRegistrars</code> method defined by the <code>LookupDiscoveryRegistration</code> interface, individually marshalling each element in the set minimizes the "all or no
 thing" aspect of the deserialization process, allowing the client to recover those proxies that can be successfully unmarshalled and to proceed with processing that might not be possible otherwise.
+</p>
+<p class="Body">
+  <a name="1009689"> </a>When constructing the return set, this method attempts to unmarshal each element of the set of marshalled proxy objects contained in the event. When failure occurs while attempting to unmarshal any of the elements of that set, this method throws an exception of type <code>LookupUnmarshalException</code>. It is through the contents of this exception that the client can recover any available proxies and perform error handling with respect to the unavailable proxies.
+</p>
+<p class="Body">
+  <a name="1009759"> </a>If the <code>getRegistrars</code> method returns successfully without throwing a <code>LookupUnmarshalException</code>, the client is guaranteed that all marshalled proxies sent in the event have each been successfully unmarshalled during that particular invocation. Furthermore, after the first such successful invocation, no more unmarshalling attempts will be made (because such attempts are no longer necessary), and all future invocations of this method are guaranteed to return an array with contents identical to the contents of the array returned by the first successful invocation.
+</p>
+<p class="Body">
+  <a name="1004851"> </a>Note that an array, rather than a single proxy, is returned by the <code>getRegistrars</code> method so that implementations of the lookup discovery service can choose to "batch" the information sent to a registration. With respect to discoveries, batching the information may be particularly useful when a client first registers with the lookup discovery service.
+</p>
+<p class="Body">
+  <a name="1004852"> </a>Upon initial registration, multiple lookup services are typically found over a short period of time, providing the lookup discovery service with the opportunity to send all of the initially discovered lookup services in only one event. Afterward, as so-called "late joiner" lookup services are found sporadically, the lookup discovery service may send events referencing only one lookup service.
+</p>
+<p class="Body">
+  <a name="1014635"> </a>Note that the event sequence numbers, as defined earlier in <a href="lds-spec.html#1003321">Section&nbsp;LD.3.2, "Event Semantics"</a>, are strictly increasing, even when the information is batched.
+</p>
+<p class="Body">
+  <a name="1014559"> </a>The <code>getGroups</code> method returns a <code>Map</code> in which the elements of the map's key set are the instances of <code>ServiceID</code> that correspond to each lookup service for which the event was constructed and sent. Each element of the returned map's value set is a <code>String</code> array containing the names of the member groups of the associated lookup service whose <code>ServiceID</code> equals to the corresponding key. This method does not make a remote call. On each invocation of this method, the same <code>Map</code> object is returned; that is, a copy is not made.
+</p>
+<p class="Body">
+  <a name="1016211"> </a> The <code>Map</code> returned by the <code>getGroups</code> method is keyed by the <code>ServiceID</code> of each lookup service in the event, rather than by the proxy of each lookup service to avoid the deserialization issues addressed by the <code>getRegistrars</code> method. Thus, client's wishing to retrieve the set of member groups corresponding to any element of the array returned by the <code>getRegistrars</code> method, must use the <code>ServiceID</code> of the desired element from that array as the key to the get method of the <code>Map</code> returned by this method and then cast to <code>String</code>[].
+</p>
+<h5 class="Heading4">
+  <a name="1016232"> </a>LD.4.2.2	 Serialized Forms
+<p><CENTER>
+<table border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000"
+       cellpadding="5" cellspacing="0" summary="serialized form of <code>RemoteDiscoveryEvent</code>">
+  <caption></caption>
+  <tr bgcolor="#CCCCCC">
+    <th>Class<br></th>
+    <th><code>serialVersionUID</code><br></th>
+    <th>Serialized Fields<br></th>
+  </tr>
+  <tr>
+    <td><code>RemoteDiscoveryEvent</code><br></td>
+    <td>-9171289945014585248L<br></td>
+    <td><code>boolean discarded</code><br>
+	<code>ArrayList marshalledRegs</code><br>
+	<code>ServiceRegistrar[] regs</code><br>
+	<code>Map groups</code>
+</td>
+  </tr>
+</table>
+</CENTER>
+
+
+
+</h5>
+<h5 class="Heading4">
+  <a name="1016233"> </a>LD.4.2.3	 The <code>LookupUnmarshalException</code> Class
+</h5>
+<p class="Body">
+  <a name="1009943"> </a>Recall that when unmarshalling an instance of <code>MarshalledObject</code>, one of the following checked exceptions is possible: 
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1014958"> </a>An <code>IOException</code>, which can occur while deserializing the object from its internal representation<p>
+  <li class="SmartList1"><a name="1014960"> </a>A <code>ClassNotFoundException</code>, which can occur if, while deserializing the object from its internal representation, either the class file of the object cannot be found, or the class file of an interface or class referenced by the object being deserialized cannot be found. Typically, a <code>ClassNotFoundException</code> occurs when the codebase from which to retrieve the needed class file is not currently available
+</ul>
+
+<p class="Body">
+  <a name="1009934"> </a>The <code>LookupUnmarshalException</code> class provides a mechanism that clients of the lookup discovery service may use for efficient handling of the exceptions that may occur when unmarshalling elements of a set of marshalled instances of the <code>ServiceRegistrar</code> interface. When elements in such a set are unmarshalled, the <code>LookupUnmarshalException</code> class may be used to collect and report pertinent information generated when failure occurs during the unmarshalling process.
+</p>
+<pre  class="Preformatted">
+package net.jini.discovery;
+
+public class LookupUnmarshalException extends Exception {
+    public LookupUnmarshalException
+                    (ServiceRegistrar[] registrars,
+                     MarshalledObject[] marshalledRegistrars,
+                     Throwable[] exceptions) {...}
+    public LookupUnmarshalException
+                    (ServiceRegistrar[] registrars,
+                     MarshalledObject[] marshalledRegistrars,
+                     Throwable[] exceptions,
+                     String message) {...}
+    public ServiceRegistrar[] getRegistrars() {...}
+    public MarshalledObject[] getMarshalledRegistrars() {...}
+    public Throwable[] getExceptions() {...}
+}
+</pre>
+<p class="Body">
+  <a name="1009983"> </a>The <code>LookupUnmarshalException</code> class is a subclass of <code>Exception</code>, adding the following additional items of abstract state: 
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1010004"> </a>A set of <code>ServiceRegistrar</code> instances in which each element is the result of a successful unmarshalling attempt<p>
+  <li class="SmartList1"><a name="1010005"> </a>A set of marshalled instances of <code>ServiceRegistrar</code> in which each element is the result of an unsuccessful unmarshalling attempt<p>
+  <li class="SmartList1"><a name="1015576"> </a>A set of exceptions (<code>IOException</code>, <code>ClassNotFoundException</code>, or some unchecked exception) in which each element corresponds to one of the unsuccessful unmarshalling attempts
+</ul>
+
+<p class="Body">
+  <a name="1015578"> </a>When exceptional conditions occur while unmarshalling a set of marshalled instances of <code>ServiceRegistrar</code>, the <code>LookupUnmarshalException</code> class can be used not only to indicate that an exceptional condition has occurred, but also to provide information that can be used to perform error handling activities such as:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1015003"> </a>Determining if it is feasible to continue with processing<p>
+  <li class="SmartList1"><a name="1015004"> </a>Reporting errors<p>
+  <li class="SmartList1"><a name="1015005"> </a>Attempting recovery<p>
+  <li class="SmartList1"><a name="1015006"> </a>Performing debug activities
+</ul>
+
+<h5 class="Heading4">
+  <a name="1009984"> </a>LD.4.2.4	 The Semantics
+</h5>
+<p class="Body">
+  <a name="1009797"> </a>The constructor of the <code>LookupUnmarshalException</code> class has two forms. The first form of the constructor takes the following parameters as input:
+</p>
+<ul>
+
+  <li class="SmartList1"><a name="1010074"> </a>An array containing the set of instances of <code>ServiceRegistrar</code> that were successfully unmarshalled<p>
+  <li class="SmartList1"><a name="1010092"> </a>An array containing the set of marshalled <code>ServiceRegistrar</code> instances that could not be unmarshalled<p>
+  <li class="SmartList1"><a name="1010106"> </a>An array containing the set of exceptions that occurred during the unmarshalling process
+</ul>
+
+<p class="Body">
+  <a name="1009804"> </a>The second form of the constructor takes the same arguments as the first and one additional argument: a <code>String</code> describing the nature of the exception.
+</p>
+<p class="Body">
+  <a name="1015620"> </a>Each element in the exceptions parameter should be an instance of <code>IOException</code>, <code>ClassNotFoundException</code>, or some unchecked exception. Furthermore, there is a one-to-one correspondence between each element in the exceptions parameter and each element in the <code>marshalledRegistrars</code> parameter. That is, the element of the exceptions parameter corresponding to index <em class="Emphasis">i</em> should be an instance of the exception that occurred while attempting to unmarshal the element at index <em class="Emphasis">i</em> of the <code>marshalledRegistrars</code> parameter.
+</p>
+<p class="Body">
+  <a name="1010328"> </a>If the number of elements in the exceptions parameter does not equal the number of elements in the <code>marshalledRegistrars</code> parameter, the constructor will throw an <code>IllegalArgumentException</code>.
+</p>
+<p class="Body">
+  <a name="1009805"> </a>The <code>getRegistrars</code> method is an accessor method that returns an array consisting of instances of <code>ServiceRegistrar</code>, where each element of the array corresponds to a successfully unmarshalled object. Note that the same array is returned on each invocation of this method; that is, a copy is not made.
+</p>
+<p class="Body">
+  <a name="1010167"> </a>The <code>getMarshalledRegistrars</code> method is an accessor method that returns an array consisting of instances of <code>MarshalledObject</code>, where each element of the array is a marshalled instance of the <code>ServiceRegistrar</code> interface and corresponds to an object that could not be successfully unmarshalled. Note that the same array is returned on each invocation of this method; that is, a copy is not made.
+</p>
+<p class="Body">
+  <a name="1010187"> </a>The <code>getExceptions</code> method is an accessor method that returns an array consisting of instances of Throwable, where each element of the array corresponds to one of the exceptions that occurred during the unmarshalling process. Each element in the return set is an instance of <code>IOException</code>, <code>ClassNotFoundException</code>, or some unchecked exception. Additionally, there should be a one-to-one correspondence between each element in the array returned by this method and the array returned by the <code>getMarshalledRegistrars</code> method. Note that the same array is returned on each invocation of this method; that is, a copy is not made.
+</p>
+<h5 class="Heading4">
+  <a name="1014953"> </a>LD.4.2.5	 Serialized Forms
+<p><CENTER>
+<table border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000"
+       cellpadding="5" cellspacing="0" summary="serialized forms of <code>LookupUnmarshalException</code>">
+  <caption></caption>
+  <tr bgcolor="#CCCCCC">
+    <th>Class<br></th>
+    <th><code>serialVersionUID</code><br></th>
+    <th>Serialized Fields<br></th>
+  </tr>
+  <tr>
+    <td><code>LookupUnmarshalException</code><br></td>
+    <td>2956893184719950537L<br></td>
+    <td><code>ServiceRegistrar[] registars<br>	
+	      MarshalledObject[] marshalledRegistrars<br>
+ 	      Throwable[] exceptions</code></td>
+  </tr>
+</table>
+</CENTER>
+
+
+
+</h5>
+<p class="Body">
+  <a name="1014780"> </a>
+<h2 class="Heading1A">
+  <a name="01886"> </a>LD.5	 History	 
+</h2>
+ 
+
+
+<table align="center" border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000" cellpadding="5" cellspacing="0" summary="changes made to this specification">
+  <caption><p class="Body">
+  <a name="01887"> </a>
+</p>
+</caption>
+  <tr bgcolor="#CCCCCC">
+    <th>Version</th>
+    <th>Description</th>
+  </tr>
+    <tr>
+    <td>v1.0</td>
+    <td>Initial release of this specification</td>
+  </tr>
+  <tr>
+    <td>v2.0</td>
+    <td>Defined indefinite and definite exceptions, and removed references to bad object and bad invocation exceptions.<br>
+Miscellaneous corrections.</td>
+  </tr>
+</table>
+</p>
+</blockquote>
+<h3 class="Heading2">
+  <a name="0188"> </a>		 License	 
+</h3>
+<p>
+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
+<ul>
+     <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
+</ul>
+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.
+</blockquote>
+
+<hr>
+<a href="#skip" title="Skip navigation bar"></a>
+<table width="100%"><tr>
+<td align=left><a href="../../spec-index.html">Spec Index</a>
+<td align=right><em>A Collection of Jini Technology Helper Utilities and Services Specifications</em></td>
+</tr></table>
+<a name="skip"></a>
+
+<hr>
+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
+<ul>
+     <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
+</ul>
+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.
+
+</body>
+</html>
+
+<!-- This HTML file was initially created with Quadralay WebWorks Publisher 3.5.0 -->
+<!-- by Susan Snyder -->
+<!-- Last updated: 01/27/05 -->