Docsity
Docsity

Prépare tes examens
Prépare tes examens

Étudies grâce aux nombreuses ressources disponibles sur Docsity


Obtiens des points à télécharger
Obtiens des points à télécharger

Gagnz des points en aidant d'autres étudiants ou achete-les avec un plan Premium


Guides et conseils
Guides et conseils


Exercice d’application en Java RMI, Notes de Informatique

Typologie: Notes

2018/2019

Téléchargé le 18/06/2019

Aela_Por
Aela_Por 🇫🇷

4.3

(46)

360 documents

1 / 27

Toggle sidebar

Cette page n'est pas visible dans l'aperçu

Ne manques pas les parties importantes!

bg1
CNAM Samia Bouzefrane
1 Exercices en NFP111
Exercice d’application en Java RMI
Nous disposons de deux services implantés sous forme d’objets ObjetString et
ObjetCalcul: un qui réalise des opérations sur les chaînes de caractère, l’autre qui réalise
du calcul numérique. Pour simplifier, l’objet ObjetString offre une seule méthode
NbOccurrences qui calcule le nombre d’occurrences d’un caractère dans une chaîne de
caractères (un mot) et l’objet ObjetCalcul offre une seule méthode add qui calcule la
somme de deux nombres. Voici le code de chacune de ces méthodes.
public int add (int a, int b) {
return a+b;
}
public int NbOccurrences(String c, String mot) {
int longueur=ChaineOrigine.length();
int Nb=0;
for (int i=0; i<longueur; i++)
{
if ((ChaineOrigine.substring(i, i+1)).equals(c))
Nb++;
}
return Nb;
}
1. On souhaite rendre chacune de ces méthodes accessibles à distance. Donnez alors la
structure des interfaces qui seront partagées par le serveur et le client sachant que
chaque méthode appartient à un objet distinct.
2. Compléter le code de ces méthodes afin qu’elles puissent gérer les erreurs dues à leur
appel à distance.
3. Sachant que toute méthode Java appelée par un programme Java distant doit
appartenir à un objet accessible à distance.
Donnez la structure des classes Java qui vont représenter respectivement l’objet
ObjetString et l’objet ObjetCalcul.
4. Si les objets ObjetString et ObjetCalcul doivent être installés sur la machine
clementine.cnam.fr, quelles sont les autres classes Java à implanter sur la
machine clementine. Donnez leur structure générale.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b

Aperçu partiel du texte

Télécharge Exercice d’application en Java RMI et plus Notes au format PDF de Informatique sur Docsity uniquement!

Exercice d’application en Java RMI

Nous disposons de deux services implantés sous forme d’objets ObjetString et

ObjetCalcul: un qui réalise des opérations sur les chaînes de caractère, l’autre qui réalise

du calcul numérique. Pour simplifier, l’objet ObjetString offre une seule méthode

NbOccurrences qui calcule le nombre d’occurrences d’un caractère dans une chaîne de

caractères (un mot) et l’objet ObjetCalcul offre une seule méthode add qui calcule la

somme de deux nombres. Voici le code de chacune de ces méthodes.

public int add (int a, int b) {

return a+b; }

public int NbOccurrences(String c, String mot) { int longueur=ChaineOrigine.length(); int Nb=0; for (int i=0; i

5. Donnez les commandes à lancer sur la machine clementine afin que les méthodes

add et NbOccurrences puissent être appelées par des clients distants si le service

de noms est activé sur le port 2001.

6. Ecrire le programme du client qui doit être lancé sur une autre machine.

public int NbOccurrence (String c, String ChaineOrigine) throws RemoteException {

int longueur=ChaineOrigine.length(); int Nb=0; for (int i=0; i } // fin de la classe

5. Si le service de noms doit être activé sur le port 2001 alors il faudra que les objets

ObjetString et ObjetCalcul soient enregistrés sur un rmiregistry de

numéro de port 2001. Comme l’enregistrement est fait par le serveur d’objets, on doit

modifier les lignes suivantes de la classe Serveur :

Naming.rebind("rmi://clementine.cnam.fr:1099/Mot", rev); ... Naming.rebind("rmi://clementine.cnam.fr:1099/Addition", r);

Par les lignes suivantes :

Naming.rebind("rmi://clementine.cnam.fr: 2001 /Mot", rev); ... Naming.rebind("rmi://clementine.cnam.fr: 2001 /Addition", r);

Les commandes suivantes doivent être lancées sur la machine clementine afin que

les objets ObjetCalcul et ObjetString soient accessibles par des clients

distants :

D’abord compiler les programmes Java (les interfaces, les objets et le serveur).

Clementine> javac *.java

On obtient des fichiers .class

Clementine> ls ObjetStringInterface.java ObjetString.java Serveur.java ObjetCalculInterface.java ObjetCalcul.java

ObjetStringInterface.class ObjetString.class Serveur.class ObjetCalcul.class ObjetCalculInterface.class fichier.policy

Générer les stubs associés aux objets ObjetCalcul et ObjetString :

Clementine> rmic –v1.2 ObjetCalcul Clementine> rmic –v1.2 ObjetString Clementine> ls ObjetStringInterface.java ObjetString.java Serveur.java ObjetCalculInterface.java ObjetCalcul.java fichier.policy

ObjetStringInterface.class ObjetString.class Serveur.class ObjetCalcul.class ObjetCalculInterface.class ObjetString_Stub.class ObjetCalcul_Stub.class

Lancer le service de noms (rmiregistry) qui va accueillir les références des objets

distribués. Mais pour cela, il doit utiliser une politique de sécurité définie dans un

fichier, par exemple fichier.policy.

Clementine>more fichier.policy grant {

ObjetCalculInterface a= (ObjetCalculInterface) Naming.lookup("rmi://clementine.cnam.fr:2001/Ad

dition"); somme = a.add(Nb, somme); } System.out.println(" Dans la phrase /"+ligne+"/, il y a "+somme+" occurrences de " + c);

}catch (Exception e) { System.out.println("Erreur d'acces a un objet distant"); System.out.println(e.toString()); } } }

Le répertoire du programme client doit contenir les interfaces distantes utilisées par le

client ainsi que les stubs des objets distants, qui sont les représentants locaux de ces

objets.

AutreMachine>ls Client.java ObjetCalculInterface.class ObjetStringInterface.class

ObjetCalcul_Stub.class Objetstring_Stub.class fichier.policy

AutreMachine>javac Client.java

Ensuite lancer l’exécution du client en spécifiant la même politique de sécurité que

celle du registre rmi.

AutreMachine>java –Djava.security.policy=fichier.policy Client e il etait une fois dans l’ouest Dans la phrase /e il etait une fois dans l’ouest/, il y a 3 occurrences de e

AutreMachine>

Exercice d’application en CORBA

Projection en Java 1.4 ou plus

Soit la spécification IDL suivante partagée par le serveur et le client et qui offre deux

interfaces : une pour traiter une chaîne de caractères, l'autre pour incrémenter un compteur

distant :

module ServicesApp { exception NbDeMotsIllegal { };

interface ObjetString { long NombreDeMots(in string chaine) raises (NbDeMotsIllegal); long NbOccurrences(in string c, in string mot); };

interface ObjetCalcul { attribute long somme; void increment(in long pas); };

1. En supposant qu'on utilise le compilateur idlj de la JDK pour faire la projection en

Java, donnez la commande nécessaire pour générer le stub d'un client se trouvant sur

une machine A. Citez tous les fichiers générés dans ce cas.

2. Utiliser le compilateur idlj pour générer le squelette côté serveur. Citez tous les

fichiers générés dans ce cas sachant que le serveur se trouve sur une machine B.

3. Ecrire le programme du serveur sachant que ce dernier doit créer deux servants (deux

objets) étant donné que la spécification IDL offre deux interfaces.

4. Compiler l'ensemble des classes Java y compris le serveur que l'on vient d'écrire afin de

lancer le service de nommage de CORBA sur le port 2000.

5. Ecrire le programme du client sur la machine A. Le client a pour rôle de lire une phrase

saisie par l’utilisateur, d’afficher le nombre de mots la composant ainsi que le nombre

d’occurrences d’un caractère dans la phrase.

6. La classe NbDeMotsIllegal.java générée du côté client et du côté serveur est

donnée ci-dessous. Compléter cette classe au niveau du client afin qu'elle puisse

générer une erreur si le nombre de mots d’une phrase est plus petit que 2.

package ServicesApp;

  • ServicesApp/NbDeMotsIllegal.java

1. La commande est la suivante (pour JDK1.3 ou sup) :

machineA> ls machineA> Specification.idl machineA> idlj -fall Specification.idl machineA>ls Specification.idl ServicesApp machineA> ls ServicesApp _ObjetCalculStub.java ObjetCalculHolder.java _ObjetStringStub.java ObjetCalculOperations.java NbDeMotsIllegal.java ObjetString.java NbDeMotsIllegalHelper.java ObjetStringHelper.java NbDeMotsIllegalHolder.java ObjetStringHolder.java ObjetCalcul.java ObjetStringOperations.java ObjetCalculHelper.java ObjetCalculPOA.java ObjetStringPOA.java

machineA>

Nous constatons que pour chaque interface IDL, les fichiers suivants sont générés :

1.un fichier Operations qui définit les méthodes distantes à

invoquer

2.un fichier Helper qui contient les méthodes de lecture,

d'écriture et de conversion

3.un fichier _Stub qui représente le proxy

4. un fichier Holder qui gère les paramètres out et inout.

5.un fichier POA qui est le squelette utilisé côté serveur

Concernant l'exception NbDeMotsIllegal définie dans le module IDL, une classe java de

même nom est générée ainsi que des classes de type Helper et Holder.

2. Pour générer le squelette du serveur, on lance la commande suivante sur la machine B :

machineB> ls machineB> Specification.idl machineB> idlj -fall Specification.idl machineB>ls machineA>ls Specification.idl ServicesApp machineA> ls ServicesApp _ObjetCalculStub.java ObjetCalculHolder.java _ObjetStringStub.java ObjetCalculOperations.java NbDeMotsIllegal.java ObjetString.java NbDeMotsIllegalHelper.java ObjetStringHelper.java NbDeMotsIllegalHolder.java ObjetStringHolder.java ObjetCalcul.java ObjetStringOperations.java ObjetCalculHelper.java ObjetCalculPOA.java ObjetStringPOA.java

machineB>

Les mêmes fichiers sont générés côté serveur et côté client même si le squelette et la souche

ne seront pas nécessaires simultanément sur les mêmes machines.

L’option –fall est utilisée car –fserver et –fclient ne génèrent pas tous les fichiers nécessaires.

Vous pouvez tester pour voir.

3. Le programme du serveur est le suivant :

import java.util.StringTokenizer;

import org.omg.CORBA.ORB; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContextExt;

import org.omg.CosNaming.NamingContextExtHelper; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAHelper;

import ServicesApp.ObjetCalculPOA; import ServicesApp.ObjetString;

import ServicesApp.ObjetStringHelper; import ServicesApp.ObjetStringPOA;

public class Serveur { public static void main(String args[]) { try { // creer et initialiser l'ORB ORB orb=ORB.init(args, null);

//obtenir la reference de rootpoa & activer le POAManager POA rootpoa =

POAHelper.narrow(orb.resolve_initial_references("RootPOA")); rootpoa.the_POAManager().activate();

// creer une instance du servant et l'enregistrer dans l'ORB ObjetStringServant revRef1= new ObjetStringServant();

//obtenir la reference CORBA du servant

org.omg.CORBA.Object ref1 = rootpoa.servant_to_reference(revRef1); ObjetString href = ObjetStringHelper.narrow(ref1);

// recuperer le contexte de nommage org.omg.CORBA.Object objRef= orb.resolve_initial_references("NameService"); NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

//bind the Object Reference in Naming

String name1 = "MyString"; NameComponent path1[] = ncRef.to_name( name1 ); ncRef.rebind(path1, href);

//bind the Object Reference in Naming

String name2 = "MyComputing"; NameComponent path2[] = ncRef.to_name( name2 ); ncRef.rebind(path2, href);

System.out.println("ReverseServer est pret et est en attente ...");

// wait for invocations from clients orb.run();

catch(Exception e) {

System.err.println("Erreur : "+e); e.printStackTrace(System.out);

machineB>

5. Voici un exemple de programme client :

import java.io.BufferedReader; import java.io.InputStreamReader;

import java.util.StringTokenizer;

import org.omg.CORBA.ORB;

import org.omg.CosNaming.NamingContextExt; import org.omg.CosNaming.NamingContextExtHelper;

import ServicesApp.ObjetCalcul; import ServicesApp.ObjetCalculHelper; import ServicesApp.ObjetString;

import ServicesApp.ObjetStringHelper;

public class Client {

public static void main (String args[]) { try { // creer et initialiser l'ORB ORB orb = ORB.init(args, null);

//recuperer le contexte de nommage org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

// demander la reference de l'objet au service de noms String nom1 = "MyString"; ObjetString Ref1 = ObjetStringHelper.narrow

(ncRef.resolve_str(nom1));

// demander la reference de l'objet au service de noms

String nom2 = "MyComputing"; ObjetCalcul Ref2 = ObjetCalculHelper.narrow (ncRef.resolve_str(nom2));

// faire appel aux objets servant BufferedReader entree = new BufferedReader(new InputStreamReader(System.in)); String ligne= entree.readLine(); //String ligne="e est une enfant malade" ;

try { int nbMots=Ref1.NombreDeMots(ligne); System.out.println("La phrase saisie est composee de " + nbMots + " mots"); } catch (ServicesApp.NbDeMotsIllegal e) { System.out.println("Erreur : " + e); System.exit(0); }

StringTokenizer st= new StringTokenizer(ligne); String c= st.nextToken(); String mot=st.nextToken(); Ref2.somme(Ref1.NbOccurrences(c, mot));

while(st.hasMoreTokens()) { mot=st.nextToken();

Ref2.increment(Ref1.NbOccurrences(c, mot)); }

System.out.println("Dans la phrase /" + ligne + "/, il y a " +

Ref2.somme()+ " occurrences de " + c);

catch(Exception e) { System.out.println("Erreur : " + e); e.printStackTrace(System.out); } } // fin du main

} // fin de la classe

6. Toute classe qui hérite de la classe Exception doit contenir une méthode toString().

Cette méthode est appelée à chaque fois qu'on fait appelle à cette classe suite à un erreur :

package ServicesApp;

  • ServicesApp/NbDeMotsIllegal.java
  • Generated by the IDL-to-Java compiler (portable), version "3.0"
  • from Specification.idl
  • mercredi 10 mars 2004 14 h 06 CET */

public final class NbDeMotsIllegal extends org.omg.CORBA.UserException implements org.omg.CORBA.portable.IDLEntity { public NbDeMotsIllegal () { } // ctor

public String toString() { return ("La chaine doit etre composee d'au moins deux mots!"); }

} // class NbDeMotsIllegal

7. Le programme du client doit être d’abord compilé :

machineB>javac Client.java ServicesApp/*.java

machineB>ls

Client.class Client.java ServicesApp Specification.idl

machineB>

Le Client est lancé en spécifiant le numéro de port du service de nommage CORBA ainsi

que le nom de la machine du serveur.

machineA>java Client -ORBInitialHost clementine.cnam.fr -ORBInitialPort

2000 e il etait une fois dans l'ouest La phrase saisie est composee de 7 mots Dans la phrase /e il etait une fois dans l'ouest/, il y a 3 occurrences de e

machineA>

Autre exécution :

Exercice sur les EJB Session avec état

Soit un site de commerce électronique appartenant à un fournisseur de matériel informatique.

Une page principale permet à l’utilisateur de s’inscrire, donc de saisir son nom et un mot de

passe qu’il aura choisi.

Après inscription, une nouvelle page s’affiche contenant les caractéristiques de machines

disponibles. L’utilisateur devra choisir les caractéristiques de la machine qu’il souhaite

commander.

1. Ecrire une servlet qui permet d’afficher les pages décrites ici sachant que les informations

que devra saisir l’utilisateur sont les suivantes :

- Taille de la mémoire centrale

- Fréquence du processeur

- Avec Graveur de CD et/ou de DVD

- Type du système d’exploitation.

2. Sachant que la servlet devra transmettre les informations saisies à un composant EJB, écrire

la classe correspondant à un EJB Session qui consiste à récupérer les informations saisies.

Quel type de EJB Session pensez-vous utiliser? Pourquoi?

3. Donnez les différentes étapes nécessaires pour que cette application soit opérationnelle sur

un serveur d’application?

Solution

1. Une solution serait de créer un fichier index.html pour l’inscription de l’utilisateur, qui

appelle une servlet qui génère un formulaire pour la saisie de la configuration de la

machine à commander.

Le fichier index.html :

Commande de Matériel Vous êtes sur un site de commerce électronique Prenez le soin de vous inscrire

Tapez votre nom : Tapez votre mot de passe :

Le fichier ConfigurationServlet.java. Cette servlet est composée de deux méthodes doPost et

doGet. La première sert à récupérer le login et le mot de passe et génère le formulaire alors

que la deuxième méthode sert à récupérer les caractéristiques saisies et appelle un composant

EJB pour lui transmettre ces informations. La méthode getConfigRef sert à associer une

session de la servlet (càd une connexion client) à un composant EJB. Il y aura autant de

clients connectés que de sessions, par conséquents de composants créés, car chaque session

devra gérer l’état du client associé.

import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Hashtable;

import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;

public class ConfigurationServlet extends HttpServlet { private static final String CONTENT_TYPE = "text/html"; private ConfigHome configHome;

// à l'initialisation de la servlet, on récupère la référence de // l’interface Home de Config

out.println("ConfigServlet"); out.println(" Voici la Configuration que vous

avez choisie pour votre Machine "); Hashtable list = cf.listerCaracteristique(); if (list != null){ out.println("

=> " + list.get("MC")+ "

"); out.println("

=> " +

list.get("PROC")+ "

"); out.println("

=> " + list.get("CD_WRITER")+ "

");

out.println("

=> " + list.get("DVD_WRITER")+ "

"); out.println("

=> " +

list.get("SE")+ "

");

}else out.println("

=> AUCUN ELEMENT SELECTIONNE !!

"); out.println(""); out.flush() ; out.close() ;

public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println ("ENTRE DANS POST") ; response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter();

Config cf = getConfigRef(request);

cf.setNomClient(request.getParameter("nom")); cf.setPassword(request.getParameter("passwd"));

out.println("ConfigServlet");

out.println(" Veuillez choisir la Configuration de votre Machine "); afficherFormulaire(out); out.println(""); out.flush() ; out.close() ; }

// une méthode auxiliaire qui permet de générer le formulaire private void afficherFormulaire(PrintWriter out) { out.println("");

out.println("Donnez la taille de la Mémoire : "); out.println(""); out.println(""); out.println(""); out.println(" "); out.println("Donnez la fréquence du Processeur : "); out.println("");

out.println(""); out.println(""); out.println(" "); out.println("Avec un Graveur de :"); out.println(" CD/ROM"); out.println(" DVD"); out.println(" Avec un Systeme d'Exploitation :"); out.println(" Windows"); out.println(" Linux "); out.println(""); out.println(""); out.println(""); // MC, PROC, CD_WRITER,DVD_WRITER , SE

Pour faire le lien entre les différentes invocations en provenance d'un même client HTML, on

utilise classiquement la notion de session offerte par l'interface HttpSession de l'API des

servlets. L'objet HttpSession se comporte comme une Hashtable. Il permet le stockage de

clés avec des valeurs associées. Par conséquent un objet HttpSession est créé pour chaque

client dès la première interaction avec la servlet. En même temps, une instance de Config est

créée et est stockée dans l'objet HttpSession (voir méthode getConfigRef). L'interface

ConfigHome par contre sera la même pour tous les clients (voir méthode init).

2. Un Bean Session avec état sera nécessaire car les informations saisies vont caractériser

chaque client connecté. Un EJB Session aura besoin de deux interfaces : une interface métier

appelée Config et une interface de gestion de cycle de vie appelée ConfigHome.