Localisez les services avec le service de recherche Jini

Le service de recherche Jini, le composant central de l'infrastructure d'exécution de Jini, offre aux clients Jini un moyen flexible et puissant de trouver des services Jini. Il permet aux fournisseurs de services d'annoncer leurs services et permet aux clients de localiser et de solliciter l'aide de ces services.

Pour interagir avec le service de recherche, le client doit d'abord obtenir un objet de registre de service via la découverte, un protocole au niveau du réseau utilisé par l'infrastructure d'exécution de Jini. La découverte permet aux clients et aux services de localiser les services de recherche. (Pour plus d'informations sur la découverte, voir Ressources.) L' service registrarobjet, qui implémente l' net.jini.core.lookup.ServiceRegistrarinterface, permet au client d'interagir avec le service de recherche. Pour trouver les services souhaités, les clients créent ServiceTemplateune instance de classe net.jini.core.lookup.ServiceTemplateet la transmettent à l'une des deux lookup()méthodes déclarées dans l' ServiceRegistrarinterface. Chaque lookup()méthode envoie le modèle de service au service de recherche, qui exécute la requête et renvoie les objets de service correspondants au client.

En général, un client recherche un service par type Java, généralement une interface. Par exemple, si un client doit utiliser une imprimante, il compose un modèle de service qui comprend un Classobjet pour une interface bien connue avec les services d'imprimante. Tous les services d'impression implémentent l'interface. Le service de recherche renvoie un objet de service (ou des objets) qui implémentent cette interface. Vous pouvez inclure des attributs dans le modèle de service pour réduire le nombre de correspondances pour une telle recherche basée sur le type. Le client utilise le service d'impression en invoquant sur l'objet de service les méthodes déclarées dans l'interface connue.

La classe ServiceTemplate

Avec la ServiceTemplateclasse, vous pouvez exprimer les critères de recherche pour les recherches Jini. La classe se compose uniquement de ces trois champs publics:

public Entry [] attributeSetTemplates; public ServiceID serviceID; public Class [] serviceTypes;

ServiceTemplaten'a pas de méthodes, et ses instances servent simplement de conteneurs de type «struct» pour les requêtes de service de recherche. Les correspondances sont effectuées comme décrit par l'extrait suivant de ServiceTemplatela page javadoc de:

Les éléments du service de recherche sont mis en correspondance à l'aide d'une instance de [ ServiceTemplate]. Un élément de service ( item) correspond à un modèle de service ( tmpl) si:

  • item.serviceIDégale tmpl.serviceID(ou si tmpl.serviceIDest null)
  • item.service [l'objet de service] est une instance de chaque type dans tmpl.serviceTypes
  • item.attributeSets contient au moins une entrée correspondante pour chaque modèle d'entrée dans tmpl.attributeSetTemplates

Une entrée correspond à un modèle d'entrée si la classe du modèle est la même que, ou une superclasse de, la classe de l'entrée, et chaque champ non nul dans le modèle est égal au champ correspondant de l'entrée. Chaque entrée peut être utilisée pour correspondre à plus d'un modèle. Notez que dans un modèle de service, pour serviceTypeset attributeSetTemplates, un champ nul équivaut à un tableau vide; les deux représentent un joker.

Comme décrit ici, le modèle de service peut inclure une référence à un tableau d' Classobjets. Ces objets indiquent au service de recherche le ou les types Java de l'objet de service souhaité par le client. Le modèle de service peut également inclure un ID de service, qui identifie de manière unique un service, et des attributs, qui doivent correspondre exactement aux attributs téléchargés par le fournisseur de services dans l'élément de service. Le modèle de service peut également contenir des caractères génériques pour l'un de ces champs. Un caractère générique dans le champ ID de service, par exemple, correspondra à n'importe quel ID de service.

Les méthodes lookup ()

Les méthodes de ServiceRegistrars lookup()prennent deux formes surchargées. Les deux formes diffèrent principalement par le nombre de correspondances et d'articles de service que chacune renvoie. Le formulaire à deux paramètres peut renvoyer plusieurs correspondances de la requête exprimée dans ServiceTemplate, tandis que le formulaire à un paramètre ne renvoie qu'une seule correspondance. En outre, le formulaire à deux paramètres renvoie des éléments de service entiers; le formulaire à un paramètre renvoie uniquement l'objet de service.

La forme à deux paramètres de lookup ()

Voici un extrait javadoc qui explique la forme à deux paramètres de lookup():

La recherche publique ServiceMatches (ServiceTemplate tmpl, int maxMatches) lance java.rmi.RemoteException; 

[It] renvoie, au maximum, les maxMatcheséléments correspondant au modèle, plus le nombre total d'éléments correspondant au modèle. La valeur de retour n'est jamais nullet le tableau des éléments retournés est uniquement nullsi maxMatchesest égal à zéro. Pour chaque élément retourné, si l'objet de service ne peut pas être désérialisé, le champ de service de l'élément est défini sur nullet aucune exception n'est levée. De même, si un jeu d'attributs ne peut pas être désérialisé, cet élément du attributeSetstableau est défini sur nullet aucune exception n'est levée.

Voici la ServiceMatchesclasse:

package net.jini.core.lookup;

La classe publique ServiceMatches étend java.lang.Object implémente java.io.Serializable {

public ServiceItem [] articles; public int totalMatches; }

Et voici la ServiceItemclasse:

package net.jini.core.lookup;

La classe publique ServiceMatches étend java.lang.Object implémente java.io.Serializable {

public Entry [] attributeSets; service public java.lang.Object; public ServiceID serviceID; }

Comme mentionné précédemment, chaque élément du itemstableau renvoyé par le formulaire à deux paramètres est un élément de service complet, qui comprend l'objet de service, l'ID de service et tous les ensembles d'attributs. Le maxMatcheschamp aide les clients à gérer le nombre d'objets renvoyés par cela lookup().

La longueur du itemstableau dans l' ServiceMatchesobjet renvoyé est inférieure ou égale à la valeur transmise à lookup()dans maxMatches. Le nombre total d'éléments de service correspondants (renvoyés dans totalMatches) est supérieur ou égal à la longueur du itemstableau.

Par exemple, si maxMatchesvaut 50 et que le modèle de service correspond à 25 éléments, la longueur du itemstableau retourné et la valeur de totalMatchessont toutes les deux 25. Sinon, si maxMatchesest 50 mais que le modèle de service correspond à 100 éléments, la longueur du itemstableau renvoyé est 50 et la valeur de totalMatchesest 100. Lorsqu'un modèle de service correspond à plus d' maxMatcheséléments de service, les éléments de service renvoyés par les deux paramètres lookup()sont sélectionnés au hasard dans l'ensemble complet des éléments de service correspondants.

La forme à un paramètre de lookup ()

La lookup()méthode à un paramètre renvoie un objet de service correspondant choisi au hasard parmi toutes les correspondances. Voici un extrait javadoc expliquant ce formulaire:

La recherche d'objet public (ServiceTemplate tmpl) lève java.rmi.RemoteException; 
Renvoie l'objet de service (c'est-à-dire juste ServiceItem.service) à partir d'un élément correspondant au modèle, ou nulls'il n'y a pas de correspondance. Si plusieurs éléments correspondent au modèle, il est arbitraire de savoir quel objet de service est renvoyé. Si l'objet retourné ne peut pas être désérialisé, un UnmarshalExceptionest renvoyé avec la sémantique RMI standard.

Étant donné que le paramètre lookup()unique ne renvoie qu'un seul objet de service correspondant, les clients peuvent réduire le nombre de fichiers d'état et de classe d'objet téléchargés. Mais comme l'objet de service retourné est sélectionné arbitrairement, et non identifié par un ID de service ou décrit par des ensembles d'attributs associés, le client doit être sûr que tout objet de service correspondant suffira.

Les méthodes de navigation

In addition to the two lookup() methods, the ServiceRegistrar has three browsing methods, which yield information about registered service items. The three methods -- getServiceTypes(), getEntryClasses(), and getFieldValues() -- are called browsing methods because they enable clients to browse the services and attributes in the lookup service.

The getServiceTypes() method takes a ServiceTemplate (the same ServiceTemplate that is passed to the lookup() methods) and a String prefix. It returns an array of Class instances representing the most specific types (classes or interfaces) of the service objects that match the template. These service objects are neither equal to, nor a superclass of, any of the types specified in the template, and they have names that start with the specified prefix. The service object or objects for which Class instances are returned are all instances of all the types (if any) passed in the template, but the Class instances are all more specific than (and are subclasses or subinterfaces of) those types. Each class appears only once in the returned array, and in arbitrary order.

Here's what getServiceTypes() looks like:

public java.lang.Class[] getServiceTypes(ServiceTemplate tmpl, java.lang.String prefix) throws java.rmi.RemoteException; 

The getEntryTypes() method takes a ServiceTemplate and returns an array of Class instances that represent the most specific classes of entries for the service items that match the template, which either don't match any entry template or are a subclass of one. Each class appears only once in the returned array, again in arbitrary order.

Here's what getEntryClasses() looks like:

public java.lang.Class[] getEntryClasses(ServiceTemplate tmpl) throws java.rmi.RemoteException; 

The getFieldValues() method takes a ServiceTemplate, an integer index, and a String field name. It returns an array of Objects for the named field of all instances of the entry that appears in the ServiceTemplate's Entry[] array at any matching service item's passed index. Each object of a particular class and value appears only once in the returned array, and in arbitrary order.

Here's what getFieldValues() looks like:

public java.lang.Object[] getFieldValues(ServiceTemplate tmpl, int setIndex, java.lang.String field) throws java.lang.NoSuchFieldException, java.rmi.RemoteException; 

The behavior and purpose of these browsing methods can be obscure. You might think of them as tools that incrementally narrow queries of the lookup service.

For example, a client such as a graphical lookup service browser could first invoke getServiceTypes() with an empty template. The getServiceTemplate() method returns all possible service types registered in the lookup service, which the browser could display. The user could select one or more types, then push the Requery button. The browser would add that type (or types) to the service template and invoke getServiceTypes() again. A smaller list of types would be returned and displayed by the browser. The user could select one and press an Entries button. The browser would form a template with the most recently selected service type or types, and then invoke getEntryTypes(). The getEntryTypes() method would return an array of entry classes, which the browser could then display.

The user could select some entries -- and a field of a selected entry -- and push a Fields button. The browser would build a template using the currently selected service and entry types. It would then pass the index of the entry class in which the user selected the field, and the name of the selected field, to getFieldValues(). The browser would display all the values that getFieldValues() returned. With those values the user could further narrow the search for a service, eventually choosing a particular service. Thus, these methods help clients, whether or not a human user is involved, to browse the services registered in a lookup service. The arrays returned from the browsing methods can help the client further refine its queries, ultimately resulting in a ServiceTemplate that, when passed to lookup(), returns the most appropriate service object.

The notify() method

In addition to the lookup and browsing methods, the ServiceRegistrar interface also has a notify() method that notifies clients when new services register or unregister with a lookup service:

public EventRegistration notify(ServiceTemplate tmpl, int transitions, RemoteEventListener listener, MarshalledObject handback, long leaseDuration) throws RemoteException; 

You invoke notify() to register yourself (or another listener) to receive a distributed event whenever the services that match the passed ServiceTemplate undergo a state change described by the transitions parameter.

The transitions parameter is a bitwise OR of any nonempty set of these three values, defined as constants in ServiceRegistrar:

TRANSITION_MATCH_MATCH TRANSITION_MATCH_NOMATCH TRANSITION_NOMATCH_MATCH 

You build the ServiceTemplate for notify() in the same way you build it for lookup(). You can indicate explicit types, a service ID, attributes (which must exactly match), or wild cards (which match anything) in any of those fields. The transitions are based on a change (or nonchange) in the status of whatever matches your ServiceTemplate before and after any operation is performed on the lookup service.

Par exemple, TRANSITION_MATCH_MATCHindique qu'au moins un élément de service correspondait à votre modèle avant et après une opération. TRANSITION_MATCH_NOMATCHindique que, bien qu'au moins un élément de service particulier correspondait à votre modèle avant une opération, il ne correspondait plus à votre modèle après l'opération. Pour recevoir une notification lorsque de nouveaux services sont ajoutés à un service de recherche, il vous suffit de spécifier un modèle qui correspond à n'importe quel service et de passer en TRANSITION_NOMATCH_MATCHtant que transition vers la notify()méthode.

SUBHEAD_BREAK: service de recherche et serveurs de noms