1  Parallélisme

Eric Goubault (et Matthieu Martel)

Commissariat à l'Energie Atomique

Saclay

2  Reveil de serveur

Problèmes dans les méthodes précédentes:

Depuis JAVA 2 on peut activer à distance un objet distant.

3  Activation à distance

4  Inscription du service

5  Activation du service

6  En pratique

7  Pour en savoir plus: packages RMI

Voir la documentation online:

http://java.sun.com/j2se/1.4/docs/guide/rmi/package-use.html

8  Les différentes classes et interfaces

file=rmi.eps,width=25cm,clip=

9  En pratique - interface serveur activable à distance

L'interface du service ne contient que les méthodes désirées (sans argument, mais devant renvoyer une exception de type java.rmi.RemoteException - imposé par rmic):

public interface InterfaceObjetActivable 
  extends java.rmi.Remote
{  public void MethodeA() throws java.rmi.RemoteException;
   public void MethodeB() throws java.rmi.RemoteException;
  ... }
Cette interface peut être en fait implémentée par un objet activable à distance ou un service permanent UnicastRemoteObject.

10  Création d'une implémentation du serveur

11  Exemple - Création d'un objet activable à distance

public class ImplementationObjetActivable extends
             java.rmi.activation.Activatable
             implements InterfaceObjetActivable
{
  public ImplementationObjetActivable (
    java.rmi.activation.ActivationID activationID,
    java.rmi.MashalledObject data) throws
    java.rmi.RemoteException
    { super(activationID,0); }
(appelle le constructeur de la classe parent Activatable(ID,0))

12  Création d'un objet activable à distance

Enfin, la méthode implémentant le service:

  public void doSomething()
  {
    ...
  }
}

13  Activation de l'objet

14  Exemple d'une ``lampe''

(voir ~goubaul1/Cours03/RMI/Ex2)

file=expli2.eps,width=20cm,clip=

15  L'interface du serveur activable

package examples;
import java.rmi.*;

public interface RMILightBulb extends Remote {
    public void on() throws RemoteException;
    public void off() throws RemoteException;
    public boolean isOn() throws RemoteException;
}

16  Et un client possible...

(serait le même si on avait utilisé une implémentation du serveur comme instance de UnicastRemoteObject)

package examples;
import java.rmi.*;

public class LightBulbClient {
    public static void main(String args[]) {
        System.out.println("Recherche d'une lampe...");

17  Utilisation du rmiregistry

  /* voir Server */
System.setSecurityManager(new RMISecurityManager()); 
try {
  String registry = "localhost";
  if (args.length >= 1) 
    registry = args[0];
  String registration = "rmi://"+registry+
              "/ActivatableLightBulbServer";
  Remote remoteService = Naming.lookup(registration);
  RMILightBulb bulbService = (RMILightBulb) remoteService;
(permet de spécifier la machine où se trouve le serveur, et le rmiregistry correspondant)

18  Appel aux services

    System.out.println("Appel de bulbservice.on()");
    bulbService.on();
    System.out.println("Lampe : "+bulbService.isOn());

    System.out.println("Appel de bulbservice.off()");
    bulbService.off();
    System.out.println("Lampe : "+bulbService.isOn());

19  Récupération des exceptions

    } catch(NotBoundException nbe) {
      System.out.println("Pas de lampe dans le 
                        repertoire de services!");
   } catch(RemoteException re) {
   System.out.println("RMI Error - "+re);
  } catch(Exception e) {
  System.out.println("Error - "+e);
  }
 }
}

20  Le serveur activable à distance

package examples;

import java.rmi.*;
import java.rmi.activation.*;

21  Exemple d'une ``lampe''

public class ActivatableLightBulbServer 
extends Activatable implements RMILightBulb {
    public ActivatableLightBulbServer
             (ActivationID activationID, 
              MarshalledObject data) 
                throws RemoteException {
        super(activationID,0);
        setBulb(false); }

22  Services... enfin!

public boolean isOn() throws RemoteException {
  return getBulb();
}

public void setBulb(boolean value) 
  throws RemoteException {
  lightOn = value; }

public boolean getBulb() throws RemoteException {
  return lightOn; } }

23  Services... enfin!

private boolean lightOn;

public void on() throws RemoteException {
  setBulb(true);
}

public void off() throws RemoteException {
  setBulb(false);
}

24  Le main de Setup et la sécurité

package examples;
import java.rmi.*;
import java.rmi.activation.*;
import java.util.Properties;
public class Setup {
  public static void main(String[] args) throws Exception {
    System.setSecurityManager(new RMISecurityManager());

25  La sécurité

    Properties props = new Properties();
    props.put("java.security.policy",
"/users/profs/info/goubaul1/Cours03/RMI/Ex2/activepolicy");
La politique de sécurité doit être spécifiée à la ligne de commande - voir ``Exécution''.

26  Créer un descripteur de groupe

  ActivationGroupDesc.CommandEnvironment ace = null;
  ActivationGroupDesc exampleGroup = 
    new ActivationGroupDesc(props, ace);
Permet d'associer des propriétés et des droits à l'exécution.

27  Inscrire le descripteur de groupe

Récupérer le descripteur du démon rmid, puis y enregistrer le descripteur de groupe:

ActivationGroupID agi =
  ActivationGroup.getSystem().registerGroup(exampleGroup);

28  Créer un descripteur d'activation du code

Au sein du groupe nouvellement crée; on passe le nom de la classe, l'endroit où se trouve le code, et une donnée optionnelle, une version ``serialized'' de l'objet distant (de type MarshalledObject):

  String location = 
"file:/users/profs/info/goubaul1/Cours03/RMI/Ex2/";
  MarshalledObject data = null;
  ActivationDesc desc = new ActivationDesc
    (agi, "examples.ActivatableLightBulbServer",
     location, data);

29  Indiquer l'endroit où se trouve le code exécutable

On aurait pu aussi trouver le répertoire courant:

java.io.File location = new java.io.File(".");
String strLoc = "file://"
+URLEncoder.encode(location.getAbsolutePath(),"UTF-8");
System.out.println("Code \`a ex\'ecuter : "+strLoc);
L'encodage URLEncoder permet d'être compatible avec les systèmes Windows etc. On peut aussi utiliser un serveur http://... pour le chargement dynamique de classes.

30  Chargement dynamique de classes

31  Enregistrer l'objet auprès du rmid

RMILightBulb stub = (RMILightBulb)Activatable.register(desc);
System.out.println("Got stub for ActivatableLightBulbServer");
Renvoie un ``stub'' que l'on peut enregistrer auprès du serveur de services rmiregistry.

32  Enregistrer le ``stub'' auprès du rmiregistry

Naming.rebind("ActivatableLightBulbServer", mri);
System.out.println("Exported ActivatableLightBulbServer");
System.exit(0); } }
(similaire au cas d'implémentation par UnicastRemoteObject - sauf que c'est le ``stub'' et pas l'objet lui-même qui est inscrit)

33  Complément: Sécurité

34  Associer une politique de sécurité

Pour ce faire:

35  Exemple

System.setSecurityManager(new RMISecurityManager() {
  public void checkConnect(String host, int port) {}
  public void checkConnect(String host, int port, 
                           Object context) {}
});
(utilise une classe anonyme, sous-classe de RMISecurityManager dans lesquelles les méthodes checkConnect retourne faux: aucune permission de créer des sockets pour communication avec d'autres machines)

36  Autre méthode

A partir de JAVA 1.2, une autre méthode est fournie en plus:

37  La classe Policy

38  La classe Policy

39  En pratique...

Pour utiliser le fichier de permissions en question (fichier), à l'exécution du main de la classe maclasse, tout en spécifiant le répertoire contenant le code:
java -Djava.security.policy=FICHIER
     -D-Djava.rmi.server.codebase=file:/LOCATION
     MACLASSE

40  Compilation

Il faut compiler, et créer les fichiers stubs et squelettes:

(le -d . pour créer les répertoires correspondants aux packages)

41  Lancement des démons etc.

Sur la machine correspondant au serveur (ici loire):

42  Exécution

[goubaul1@loire Ex2]$ java 
  -Djava.security.policy=activepolicy 
  -Djava.rmi.server.codebase=file:/. examples.Setup
Got the stub for the ActivatableLightBulbServer
Exported ActivatableLightBulbServer
(pour spécifier la politique de sécurité)

43  Exécution d'un client

Sur cher:

[goubaul1@cher Ex2]$ java 
  -Djava.security.policy=activepolicy 
  examples.LightBulbClient loire
Looking for light bulb service
Invoking bulbservice.on()
Bulb state : true
Invoking bulbservice.off()
Bulb state : false

44  Comparaison avec UnicastRemoteObject

Le serveur lui-même (voir ~goubaul1/RMI/Ex1):

public class RMILightBulbImpl extends 
java.rmi.server.UnicastRemoteObject 
                implements RMILightBulb {
    public RMILightBulbImpl() 
    throws java.rmi.RemoteException {
      setBulb(false);
    }

    private boolean lightOn;

45  

    public void on() 
      throws java.rmi.RemoteException {
        setBulb(true); }

    public void off() 
      throws java.rmi.RemoteException {
        setBulb(false); }

    public boolean isOn() 
      throws java.rmi.RemoteException {
        return getBulb(); }

    public void setBulb(boolean value) {
        lightOn = value; }
    public boolean getBulb() {
        return lightOn; } }

46  Mais...même interface de serveur

public interface RMILightBulb extends java.rmi.Remote {
    public void on() throws java.rmi.RemoteException;
    public void off() throws java.rmi.RemoteException;
    public boolean isOn() throws java.rmi.RemoteException;
}
Et même client...

47  Exécution

Sur cher (serveur):
[goubaul1@cher Ex1]$ java LightBulbServer
Loading RMI service
RemoteStub [ref: [endpoint:[129.104.254.54:1867](local),
            objID:[0]]]

48  Exécution (client)

Sur loire (client):
[goubaul1@loire Ex1]$ java LightBulbClient cher
Looking for light bulb service
Invoking bulbservice.on()
Bulb state : true
Invoking bulbservice.off()
Bulb state : false

This document was translated from LATEX by HEVEA.