Objectif/Contenu :
JNDI permet
de s'abstraire dans un programme réparti des annuaires (de type pages
blanches = Naming; ou pages jaunes = Directory) effectivement
utilisés.
L'objet de ce TP est d'utiliser dans nos codes RMIRegistry sans le
savoir, en s'en abstrayant grâce
à JNDI. En effet, lors des opérations d'enregistrement ou de recherche
des proxy
par leur nom (String) associé, que ce soit coté serveur ou coté client,
nous avons jusqu'à présent eu besoin de faire apparaitre en dur l'URL du
RMIregistry à questionner.
L'intérêt principal est qu'aucun de nos codes coté serveur ou client n'aura de lien "en dur" avec le service de nommage effectif:
Il n'aura pas à être recompilé si l'application est déployée dans un
autre contexte d'exécution (autres adresses IPs), seules les options de
configuration des lancements des différents éléments de l'application
répartie ont besoin d'être actualisés. Evidemment, on pourrait imaginer
passer en paramètres (String[] args) l'URL du RMIRegistry, mais il est
de bonne pratique de ne pas utiliser ces arguments pour des aspects non
fonctionnels, et de préférer des arguments de configuration de JVM à la
place.
Replacé dans le cadre de votre projet, cela signifie que
serveurs et clients n'ont pas besoin d'avoir 'en dur' dans leur code
l'URL du RMI registry leur permettant d'accéder au stub de votre
registre universel : au contraire l'URL du RMIRegistry est obtenue par
simple configuration des
JVMs.
A terme (bien que vous ne devrez pas le faire pour le projet) : on pourrait enregistrer l'URL d'un RMIRegistry dans un annuaire JNDI (celle ci étant Referencable au sens JNDI).
Reprenez un code quelconque RMI qui fonctionnait auparavant !
Après vous être documenté sur JNDI et sur la partie Naming uniquement (pas besoin de regarder la partie Directory), faites en sorte d'avoir un contexte (de nommage), auprès duquel vous enregisterez votre objet distant.Réalisez les mêmes abstractions via JNDI du coté du code client: celui ci doit contacter le RMIRegistry via un context JNDI et non en dur, et pour celà, il a lui aussi besoin de configurer les bonnes propriétés au moment du lancement de la JVM. Ensuite, il utilisera lookup sur le context JNDI pour obtenir un stub vers l'objet distant.
Le but de cette question est d'installer coté client une opération
bien pratique : filtrer parmi des stubs vers des serveurs RMI, celui qui
correspond à un nom précis.
Pour cette question dans le cadre court de ce TP, instancier plusieurs objets serveurs variant à peine leur comportement
(paramétrez celà par un argument), et utilisant un nom différent dans
l'annuaire. Malgrè celà, ils exposent tous la même interface RMI.
Coté client, passez un argument (fonctionnel!) qui correspond à un mot précis que le client utilisera dans sa recherche auprès de l'annuaire. Listez le contenu de tout l'annuaire et découvrez le stub qui convient conformément à l'argument passé au lancement du client. C'est sur le stub enregistré avec cette chaine en guise de nom que vous ferez les appels de méthode RMI.
Le lancement d'un annuaire CORBA se fait sur la machine où il doit s'exécuter, et peut aussi utiliser un port autre que celui par défaut (900). avec l'option -ORBInitialPort valeurport. Son lancement se fait dans un terminal, et n'a pas besoin de se soucier de quelconques valeurs de CLASSPATH. Pour le TP, vous resterez sur la machine locale, localhost, mais ce n'est donc pas une obligation. L'annuaire n'a aucun besoin d'avoir de CLASSPATH correctement configuré. Il faudra juste que le programme qui fait rebind, et celui qui fera lookup, aient dans leur CLASSPATH le .class correspondant au stub de l'objet distant publié.
Contrairement à RMIRegistry, l'annuaire enregistre une entrée de type : Nom : Référence IIOP (=Corba) universelle de cet objet distant IIOP. L'annuaire ne stocke pas d'objets sérialisés comme le sont les stubs RMI. Il ne stocke qu'une adresse IIOP (un peu comme une adresse IP) qui correspond à un point de contact de l'objet distant sur le bus CORBA. Il n'a donc pas besoin de générer à la volée de bytecode pour désérialiser l'objet reçu lors du rebind, et le sérialiser lors du lookup. C'est pour cela qu'il n'a pas à se soucier d'un quelconque CLASSPATH!
Il faut bien comprendre que la référence publiée dans l'annuaire est une référence d'un objet qui s'expose comme un objet CORBA et non comme un objet RMI! Mais dans un souci d'interopérabilité des objets RMI avec les objets CORBA, la plateforme Java contient ce qu'il faut pour exposer un objet implémentant une java.rmi.Remote interface comme étant un objet accessible via le réseau , non pas selon le protocole JRMP, mais selon le protocole IIOP. Il devient donc possible pour des clients CORBA d'invoquer des méthodes distantes sur un objet RMI, pensant qu'ils interagissent avec un objet CORBA. Dans cet objectif, la seule modification à apporter à l'objet RMI est la suivante: au lieu d'étendre UnicastRemoteObject, l'objet distant devra étendre javax.rmi.PortableRemoteObject.
Contrairement à Java qui sait générer à la volée le bytecode d'un stub RMI si le bytecode de l'interface java.rmi.remote est disponible, ce n'est pas possible de générer à la volée un stub CORBA pour ce même objet. Il faut alors les générer à l'avance, en utilisant la commande rmic avec l'option iiop. Le fichier correspondant au stub de l'objet distant CORBA doit exister sur la JVM serveur et sur la JVM cliente.
L'annuaire Corba peut être utilisé via JNDI dans les programmes. Le code est similaire à l'usage du RMIRegistry via JNDI: vous pourrez donc reprendre les solutions données aux exercices 1 et 2! La seule précaution est de passer des valeurs de property de JVM qui permettent d'indiquer qu'il s'agit d'un service de nommage CORBA (COSNaming) et non de rmiregistry, et que le context de nommage suit les conventions de l'annuaire Corba. Les transparents fournis permettent de trouver ces informations à utiliser en vue d'un rebind ou d'un lookup sur le context de nommage.
En effet, pour le projet, il vous est suggéré (en bonus) d'appliquer ce pattern pour que le stub RMI de l'objet RMI représentant un service RMI soit en fait un objet Serializable qui en plus implante une interface java.rmi.Remote (condition obligatoire pour qu'un RMIRegistry standard veuille bien effectuer l'opération rebind). L'avantage de l'utilisation d'un smartProxy plutôt que d'un simple proxy RMI (ou CORBA), est que l'objet que l'on binde est un objet qui contient en dur (=en cache) les valeurs immuables de l'objet, ainsi qu'un champ qui correspond à la référence RMI d'un objet distant: les méthodes implantées par l'interface RMI sont de deux natures. Soit 1) elles utilisent le champ correspondant à la reférence RMI du véritable objet RMI, et déclenchent l'appel de méthode correspondant via le réseau (comme d'habitude, si le proxy n'était pas "smart"); soit 2) elles renvoient directement la réponse (immuable) à l'appel de méthode, qui donc n'a pas besoin d'etre effectué via le réseau puisque la réponse est déjà présente dans un des champs de l'objet "smart" proxy.
Page maintenue par Francoise Baude @2014-