t
t
t
t
t t 15) Informatique distribuée
tttt
15) Informatique distribuée
Texte original t Traducteur : Jean-Pierre VIDAL, Alban PEIGNIER
t
t
///
Ce chapitre contient 12 pages
1 2 3 4 5 6 7 8 9 10 11 12
\\\
t t t
t t t
t
t t t
//:! c15:jsp:SessionObject.jsp
<%--Getting and setting session object values--%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<H3><li>This session was created at
<%= session.getCreationTime() %></li></H1>
<H3><li>Old MaxInactiveInterval =
  <%= session.getMaxInactiveInterval() %></li>
<% session.setMaxInactiveInterval(5); %>
<li>New MaxInactiveInterval=
  <%= session.getMaxInactiveInterval() %></li>
</H3>
<H2>If the session object "My dog" is
still around, this value will be non-null:<H2>
<H3><li>Session value for "My dog" =  
<%= session.getAttribute("My dog") %></li></H3>
<%-- Now add the session object "My dog" --%>
<% session.setAttribute("My dog",
                    new String("Ralph")); %>
<H1>My dog's name is
<%= session.getAttribute("My dog") %></H1>
<%-- See if "My dog" wanders to another form --%>
<FORM TYPE=POST ACTION=SessionObject2.jsp>
<INPUT TYPE=submit name=submit
Value="Invalidate"></FORM>
<FORM TYPE=POST ACTION=SessionObject3.jsp>
<INPUT TYPE=submit name=submit
Value="Keep Around"></FORM>
</body></html>
///:~
t
//:! c15:jsp:SessionObject.jsp
<%--Getting and setting session object values--%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<H3><li>This session was created at
<%= session.getCreationTime() %></li></H1>
<H3><li>Old MaxInactiveInterval =
  <%= session.getMaxInactiveInterval() %></li>
<% session.setMaxInactiveInterval(5); %>
<li>New MaxInactiveInterval=
  <%= session.getMaxInactiveInterval() %></li>
</H3>
<H2>If the session object "My dog" is
still around, this value will be non-null:<H2>
<H3><li>Session value for "My dog" =  
<%= session.getAttribute("My dog") %></li></H3>
<%-- Now add the session object "My dog" --%>
<% session.setAttribute("My dog",
                    new String("Ralph")); %>
<H1>My dog's name is
<%= session.getAttribute("My dog") %></H1>
<%-- See if "My dog" wanders to another form --%>
<FORM TYPE=POST ACTION=SessionObject2.jsp>
<INPUT TYPE=submit name=submit
Value="Invalidate"></FORM>
<FORM TYPE=POST ACTION=SessionObject3.jsp>
<INPUT TYPE=submit name=submit
Value="Keep Around"></FORM>
</body></html>
///:~
t t t
The session object is provided by default so it is available without any extra coding. The calls to getID( ), getCreationTime( ) and getMaxInactiveInterval( ) are used to display information about this session object. t L'objet sessionest fourni par défaut, il est donc disponible sans code supplémentaire. Les appels de getID( ), getCreationTime( ) et getMaxInactiveInterval( ) servent à afficher des informations sur l'objet session.
t t t
When you first bring up this session you will see a MaxInactiveInterval of, for example, 1800 seconds (30 minutes). This will depend on the way your JSP/servlet container is configured. The MaxInactiveInterval is shortened to 5 seconds to make things interesting. If you refresh the page before the 5 second interval expires, then you’ll see: t Quand on ouvre la session pour la première fois on a, par exemple, MaxInactiveInterval égal à 1800 secondes (30 minutes). Ceci dépend de la configuration du conteneur JSP/servlet. MaxInactiveInterval est ramené à 5 secondes afin de rendre les choses intéressantes. Si on rafraîchit la page avant la fin de l'intervalle de 5 secondes, alors on voit :
t t t
Session value for "My dog" = Ralph
t
Session value for "My dog" = Ralph
t t t
But if you wait longer than that,
“Ralph” will become null.
t Mais si on attend un peu plus longtemps, alors » Ralph « devient null.
t t t
To see how the session information can be
carried through to other pages, and also to see the effect of invalidating a
session object versus just letting it expire, two other JSPs are created. The
first one (reached by pressing the “invalidate” button in
SessionObject.jsp) reads the session information and then explicitly
invalidates that session:

t Pour voir comment les informations de sessions sont répercutées sur les autres pages, ainsi que pour comparer le fait d'invalider l'objet session à celui de le laisser se terminer, deux autres JSP sont créées. La première (qu'on atteint avec le bouton » invalidate « de SessionObject.jsp) lit l'information de session et invalide explicitement cette session :
t t t
//:! c15:jsp:SessionObject2.jsp
<%--The session object carries through--%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<H1>Session value for "My dog"
<%= session.getValue("My dog") %></H1>
<% session.invalidate(); %>
</body></html>
///:~
t
//:! c15:jsp:SessionObject2.jsp
<%--The session object carries through--%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<H1>Session value for "My dog"
<%= session.getValue("My dog") %></H1>
<% session.invalidate(); %>
</body></html>
///:~
t t t
To experiment with this, refresh SessionObject.jsp, then immediately click the “invalidate” button to bring you to SessionObject2.jsp. At this point you will still see “Ralph,” and right away (before the 5-second interval has expired), refresh SessionObject2.jsp to see that the session has been forcefully invalidated and “Ralph” has disappeared. t Pour tester cet exemple, rafraîchir SessionObject.jsp, puis cliquer immédiatement sur le bouton invalidate pour activer SessionObject2.jsp. À ce moment on voit toujours » Ralph, « immédiatement (avant que l'intervalle de 5 secondes ait expiré). Rafraîchir SessionObject2.jsp pour voir que la session a été invalidée manuellement et que Ralph a disparu.
t t t
If you go back to SessionObject.jsp, refresh the page so you have a new 5-second interval, then press the “Keep Around” button, it will take you to the following page, SessionObject3.jsp, which does NOT invalidate the session: t En recommençant avec SessionObject.jsp, rafraîchir la page ce qui démarre un nouvel intervalle de 5 secondes, puis cliquer sur le bouton « Keep Around »], ce qui nous amène à la page suivante, SessionObject3.jsp, qui N'invalide PAS la session :
t t t
//:! c15:jsp:SessionObject3.jsp
<%--The session object carries through--%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<H1>Session value for "My dog"
<%= session.getValue("My dog") %></H1>
<FORM TYPE=POST ACTION=SessionObject.jsp>
<INPUT TYPE=submit name=submit Value="Return">
</FORM>
</body></html>
///:~
t
//:! c15:jsp:SessionObject3.jsp
<%--The session object carries through--%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<H1>Session value for "My dog"
<%= session.getValue("My dog") %></H1>
<FORM TYPE=POST ACTION=SessionObject.jsp>
<INPUT TYPE=submit name=submit Value="Return">
</FORM>
</body></html>
///:~
t t t
Because this page doesn’t invalidate the session, “Ralph” will hang around as long as you keep refreshing the page before the 5 second time interval expires. This is not unlike a “Tomagotchi” pet—as long as you play with “Ralph” he will stick around, otherwise he expires. t Dû au fait que cette page n'invalide pas la session, » Ralph « est toujours là aussi longtemps qu'on rafraîchit la page avant la fin de l'intervalle de 5 secondes. Ceci n'est pas sans ressembler à un » Tomagotchi], et » Ralph « restera là tant que vous jouerez avec lui, sinon il disparaîtra.
t t t

Creating and modifying cookies

t

Créer et modifier des cookies

t t t
Cookies were introduced in the prior section on servlets. Once again, the brevity of JSPs makes playing with cookies much simpler here than when using servlets. The following example shows this by fetching the cookies that come with the request, reading and modifying their maximum ages (expiration dates) and attaching a new cookie to the outgoing response:
t Les cookies ont été introduits dans la section précédente concernant les servlets. Ici encore, la concision des JSP rend l'utilisation des cookies plus simple que dans les servlets. L'exemple suivant montre cela en piégeant les cookies liés à une demande en entrée, en lisant et modifiant leur date d'expiration, et en liant un nouveau cookie à la réponse :
t t t
//:! c15:jsp:Cookies.jsp
<%--This program has different behaviors under
different browsers! --%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<%
Cookie[] cookies = request.getCookies();
for(int i = 0; i < cookies.length; i++) { %>
  Cookie name: <%= cookies[i].getName() %> <br>
  value: <%= cookies[i].getValue() %><br>
  Old max age in seconds:
  <%= cookies[i].getMaxAge() %><br>
  <% cookies[i].setMaxAge(5); %>
  New max age in seconds:
  <%= cookies[i].getMaxAge() %><br>
<% } %>
<%! int count = 0; int dcount = 0; %>
<% response.addCookie(new Cookie(
    "Bob" + count++, "Dog" + dcount++)); %>
</body></html>
///:~
t
//:! c15:jsp:Cookies.jsp
<%--This program has different behaviors under
different browsers! --%>
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<%
Cookie[ « cookies = request.getCookies();
for(int i = 0; i < cookies.length; i++) { %>
  Cookie name: <%= cookies[i].getName() %> <br>
  value: <%= cookies[i].getValue() %><br>
  Old max age in seconds:
  <%= cookies[i].getMaxAge() %><br>
  <% cookies[i].setMaxAge(5); %>
  New max age in seconds:
  <%= cookies[i].getMaxAge() %><br>
<% } %>
<%! int count = 0; int dcount = 0; %>
<% response.addCookie(new Cookie(
    "Bob" + count++, "Dog" + dcount++)); %>
</body></html>
///:~
t t t
Since each browser stores cookies in its own way, you may see different behaviors with different browsers (not reassuring, but it might be some kind of bug that could be fixed by the time you read this). Also, you may experience different results if you shut down the browser and restart it, rather than just visiting a different page and then returning to Cookies.jsp. Note that using session objects seems to be more robust than directly using cookies. t Chaque navigateur ayant sa manière de stocker les cookies, le résultat sera différent suivant le navigateur (ce qui n'est pas rassurant, mais peut-être réparerez-vous un certain nombre de bugs en lisant cela). Par ailleurs, il se peut aussi que l'on ait des résultats différents en arrêtant le navigateur et en le relançant, plutôt que de visiter une autre page puis de revenir à Cookies.jsp. Remarquons que l'utilisation des objets session semble plus robuste que l'utilisation directe des cookies.
t t t
After displaying the session identifier, each cookie in the array of cookies that comes in with the request object is displayed, along with its maximum age. The maximum age is changed and displayed again to verify the new value, then a new cookie is added to the response. However, your browser may seem to ignore the maximum age; it’s worth playing with this program and modifying the maximum age value to see the behavior under different browsers. t Après l'affichage de l'identifiant de session, chaque cookie du tableau de cookies arrivant avec l'objet request object est affiché, ainsi que sa date d'expiration. La date d'expiration est modifiée et affichée à son tour pour vérifier la nouvelle valeur, puis un nouveau cookie est ajouté à la réponse. Toutefois, il est possible que votre navigateur semble ignorer les dates d'expiration ; il est préférable de jouer avec ce programme en modifiant la date d'expiration pour voir ce qui se passe avec divers navigateurs.
t t t

JSP summary

t

Résumé sur les JSP

t t t
This section has only been a brief coverage of JSPs, and yet even with what was covered here (along with the Java you’ve learned in the rest of the book, and your own knowledge of HTML) you can begin to write sophisticated web pages via JSPs. The JSP syntax isn’t meant to be particularly deep or complicated, so if you understand what was presented in this section you’re ready to be productive with JSPs. You can find further information in most current books on servlets, or at java.sun.com. t Cette section était un bref apperçu des JSP ; cependant avec les sujets abordés ici (ainsi qu'avec le langage Java appris dans le reste du livre, sans oublier votre connaissance personnelle du langage HTML) vous pouvez dès à présent écrire des pages Web sophistiquées via les JSP. La syntaxe JSP n'est pas particulièrement profonde ni compliquée, et si vous avez compris ce qui était présenté dans cette section vous êtes prêts à être productifs en utilisant les JSP. Vous trouverez d'autres informations dans la plupart des livres sur les servlets, ou bien à java.sun.com.
t t t
It’s especially nice to have JSPs available, even if your goal is only to produce servlets. You’ll discover that if you have a question about the behavior of a servlet feature, it’s much easier and faster to write a JSP test program to answer that question than it is to write a servlet. Part of the benefit comes from having to write less code and being able to mix the display HTML in with the Java code, but the leverage becomes especially obvious when you see that the JSP Container handles all the recompilation and reloading of the JSP for you whenever the source is changed. t La disponibilité des JSP est très agréable, même lorsque votre but est de produire des servlets. Vous découvrirez que si vous vous posez une question à propos du comportement d'une fonctionnalité servlet, il est plus facile et plus rapide d'y répondre en écrivant un programme de test JSP qu'en écrivant une servlet. Ceci est dû en partie au fait qu'on ait moins de code à écrire et qu'on puisse mélanger le code Java et le code HTML, mais l'avantage devient particulièrement évident lorsqu'on voit que le Conteneur JSP se charge de la recompilation et du chargement du JSP à votre place chaque fois que la source est modifiée.
t t t
As terrific as JSPs are, however, it’s worth keeping in mind that JSP creation requires a higher level of skill than just programming in Java or just creating Web pages. In addition, debugging a broken JSP page is not as easy as debugging a Java program, as (currently) the error messages are more obscure. This should change as development systems improve, but we may also see other technologies built on top of Java and the Web that are better adapted to the skills of the web site designer. t Toutefois, aussi fantastiques que soient les JSP, il vaut mieux garder à l'esprit que la création de pages JSP requiert un plus haut niveau d'habileté que la simple programmation en Java ou la simple création de pages Web. En outre, debugger une page JSP morcelée n'est pas aussi facile que débugger un programme Java, car (pour le moment) les messages d'erreur sont assez obcurs. Cela changera avec l'évolution des systèmes de développement, et peut-être verrons nous d'autres technologies construites au-dessus de Java plus adaptées aux qualités des concepteurs de site web.
t t t

RMI (Remote Method Invocation)

t

RMI (Remote Method Invocation) : Invocation de méthodes distantes

t t t
Traditional approaches to executing code on other machines across a network have been confusing as well as tedious and error-prone to implement. The nicest way to think about this problem is that some object happens to live on another machine, and that you can send a message to the remote object and get a result as if the object lived on your local machine. This simplification is exactly what Java Remote Method Invocation (RMI) allows you to do. This section walks you through the steps necessary to create your own RMI objects. t Les approches traditionnelles pour exécuter des instructions à travers un réseau sur d'autres ordinateurs étaient aussi confuses qu'ennuyeuses et sujettes aux erreurs. La meilleure manière d'aborder ce problème est de considérer qu'en fait un objet donné est présent sur une autre machine, on lui envoie un message et l'on obtient le résultat comme si l'objet était instancié sur votre machine locale. Cette simplification est exactement celle que Java 1.1 Remote Method Invocation (RMI - Invocation de méthodes distantes) permet de faire. Cette section vous accompagne à travers les étapes nécessaires pour créer vos propres objets RMI.
t t t

Remote interfaces

t

Interfaces Remote

t t t
RMI makes heavy use of interfaces. When you want to create a remote object, you mask the underlying implementation by passing around an interface. Thus, when the client gets a reference to a remote object, what they really get is an interface reference, which happens to connect to some local stub code that talks across the network. But you don’t think about this, you just send messages via your interface reference. t RMI utilise beaucoup d'interfaces. Lorsque l'on souhaite créer un objet distant, l'implémentation sous-jacente est masquée en passant par une interface. Ainsi, lorsque qu'un client obtient une référence vers un objet distant, ce qu'il possède réellement est une référence intermédiaire, qui renvoie à un bout de code local capable de communiquer à travers le réseau. Mais nul besoin de se soucier de cela, il suffit de juste d'envoyer des messages par le biais de cette référence intermédiaire.
t t t
When you create a remote interface, you must follow these guidelines: t La création d'une interface distante doit respecter ces directives :
t t t
  1. The remote interface must be public (it cannot have “package access,” that is, it cannot be “friendly”). Otherwise, a client will get an error when attempting to load a remote object that implements the remote interface.
  2. The remote interface must extend the interface java.rmi.Remote.
  3. Each method in the remote interface must declare java.rmi.RemoteException in its throws clause in addition to any application-specific exceptions.
  4. A remote object passed as an argument or return value (either directly or embedded within a local object) must be declared as the remote interface, not the implementation class.
t
  1. L'interface distante doit être public (il ne peut y avoir accès package, autrement dit d'accès friendly). Sinon, le client recevra une erreur lorsqu'il tentera d'obtenir un objet distant qui implémente l'interface distante.
  2. L'interface distante doit hériter de l'interface java.rmi.Remote.
  3. Chaque méthode de l'interface distante doit déclarer java.rmi.RemoteException dans sa clause throws en plus des autres exceptions spécifiques à l'application.
  4. Un objet distant passé en argument ou en valeur de retour (soit directement ou inclus dans un objet local), doit être déclaré en tant qu'interface distante et non comme la classe d'implémentation.
t t t
Here’s a simple remote interface that represents an accurate time service: t Voici une interface distante simple qui représente un service d'heure exacte :
t t t
//: c15:rmi:PerfectTimeI.java
// The PerfectTime remote interface.
package c15.rmi;
import java.rmi.*;

interface PerfectTimeI extends Remote {
  long getPerfectTime() throws RemoteException;
} ///:~
t
//: c15:rmi:PerfectTimeI.java
// L'interface distante PerfectTime.
package c15.rmi;
import java.rmi.*;

interface PerfectTimeI extends Remote {
  long getPerfectTime() throws RemoteException;
} ///:~
t t t
It looks like any other interface except that it extends Remote and all of its methods throw RemoteException. Remember that an interface and all of its methods are automatically public. t Cela ressemble à n'importe quelle autre interface mis à part qu'elle hérite de Remote et que toutes ses méthodes émettent RemoteException. Rappelez vous qu'une interface et toutes ses méthodes sont automatiquement publiques.
t t t

Implementing the remote interface

t

Implémenter l'interface distante

t t t
The server must contain a class that extends UnicastRemoteObject and implements the remote interface. This class can also have additional methods, but only the methods in the remote interface are available to the client, of course, since the client will get only a reference to the interface, not the class that implements it. t Le serveur doit contenir une classe qui hérite de UnicastRemoteObject et qui implémente l'interface distante. Cette classe peut avoir aussi des méthodes supplémentaires, mais bien sûr seules les méthodes appartenant à l'interface distante seront disponibles pour le client puisque celui-ci n'obtiendra qu'une référence vers l'interface, et non vers la classe qui l'implémente.
t t t
You must explicitly define the constructor for the remote object even if you’re only defining a default constructor that calls the base-class constructor. You must write it out since it must throw RemoteException. t Vous devez explicitement définir le constructeur de cet objet distant même si vous définissez seulement un constructeur par défaut qui appelle le constructeur de base. Vous devez l'écrire parce qu'il doit émettre RemoteException.
t t t
Here’s the implementation of the remote interface PerfectTimeI: t Voici l'implémentation de l'interface distante PerfectTimeI:
t t t
//: c15:rmi:PerfectTime.java
// The implementation of
// the PerfectTime remote object.
package c15.rmi;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;

public class PerfectTime
    extends UnicastRemoteObject
    implements PerfectTimeI {
  // Implementation of the interface:
  public long getPerfectTime()
      throws RemoteException {
    return System.currentTimeMillis();
  }
  // Must implement constructor
  // to throw RemoteException:
  public PerfectTime() throws RemoteException {
    // super(); // Called automatically
  }
  // Registration for RMI serving. Throw
  // exceptions out to the console.
  public static void main(String[] args)
  throws Exception {
    System.setSecurityManager(
    new RMISecurityManager());
    PerfectTime pt = new PerfectTime();
    Naming.bind(
      "//peppy:2005/PerfectTime", pt);
    System.out.println("Ready to do time");
  }
} ///:~
t
//: c15:rmi:PerfectTime.java
// L'implémentation de
// l'objet distant PerfectTime.
package c15.rmi;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;

public class PerfectTime
    extends UnicastRemoteObject
    implements PerfectTimeI {
  // Implémentation de l'interface:
  public long getPerfectTime()
      throws RemoteException {
    return System.currentTimeMillis();
  }
  // Doit implémenter le constructeur
  // pour émettre RemoteException:
  public PerfectTime() throws RemoteException {
    // super(); // Appelé implicitement
  }
  // Inscription auprès du service RMI :
  public static void main(String[ « args) {
    System.setSecurityManager(
      new RMISecurityManager());
    try {
      PerfectTime pt = new PerfectTime();
      Naming.bind(
        "//peppy:2005/PerfectTime", pt);
      System.out.println("Ready to do time");
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
} ///:~
t t t
Here, main( ) handles all the details of setting up the server. When you’re serving RMI objects, at some point in your program you must: t Ici, main( ) se charge de tous les détails de mise en place du serveur. Une application qui met en service des objets RMI doit à un moment :
t t t
  1. Create and install a security manager that supports RMI. The only one available for RMI as part of the Java distribution is RMISecurityManager.
  2. Create one or more instances of a remote object. Here, you can see the creation of the PerfectTime object.
  3. Register at least one of the remote objects with the RMI remote object registry for bootstrapping purposes. One remote object can have methods that produce references to other remote objects. This allows you to set it up so the client must go to the registry only once, to get the first remote object.
t
  1. Créer et installer un gestionnaire de sécurité qui supporte RMI. Le seul disponible pour RMI fourni dans la distribution Java est RMISecurityManager.
  2. Créer une ou plusieurs instances de l'objet distant. Ici, vous pouvez voir la création de l'objet PerfectTime.
  3. Enregistrer au moins un des objets distants grâce au registre d'objets distants RMI pour des raisons d'amorçage. Un objet distant peut avoir des méthodes qui retournent des références vers les autres objets distants. En le mettant en place, le client ne doit s'adresser au registre qu'une seule fois pour obtenir ce premier objet distant.
t t t

Setting up the registry

t

Mise en place du registre

t t t
Here, you see a call to the static method Naming.bind( ). However, this call requires that the registry be running as a separate process on the computer. The name of the registry server is rmiregistry, and under 32-bit Windows you say: t Ici, vous pouvez voir un appel à la méthode statique Naming.bind( ). Toutefois, cet appel nécessite que le registre fonctionne dans un autre processus de l'ordinateur. Le nom du registre serveur est rmiregistry, et sous Windows 32-bit vous utiliserez :
t t t
start rmiregistry
t
start rmiregistry
t t t
to start it in the background. On Unix,
the command is:

t pour démarrer celui-ci en fond. Sous Unix, ce sera :
t t t
rmiregistry &
t
rmiregistry &
t t t
Like many network programs, the
rmiregistry is located at the IP address of whatever machine started it
up, but it must also be listening at a port. If you invoke the
rmiregistry as above, with no argument, the registry’s port will
default to 1099. If you want it to be at some other port, you add an argument on
the command line to specify the port. For this example, the port is located at
2005, so the rmiregistry should be started like this under 32-bit
Windows:

t Comme beaucoup d'applications réseau, le rmiregistry est localisé à l'adresse IP de la machine qui l'a démarré, mais il doit aussi écouter un port. Si vous invoquez le rmiregistry comme ci-dessus, sans argument, le port écouté par le registre sera par défaut 1099. Si vous souhaitez que ce soit un autre port, vous devez ajouter un argument à la ligne de commande pour le préciser. Dans cet exemple, le port sera 2005, ainsi le rmiregistry devra être démarré de cette manière sous Windows 32-bit :
t t t
start rmiregistry 2005
t
start rmiregistry 2005
t t t
or for Unix:

t ou pour Unix:
t t t
rmiregistry 2005 &

t
rmiregistry 2005 &
t t t
The information about the port must also
be given to the bind( ) command, as well as the IP address of the
machine where the registry is located. But this brings up what can be a
frustrating problem if you’re expecting to test RMI programs locally the
way the network programs have been tested so far in this chapter. In the JDK
1.1.1 release, there are a couple of
problems:[76]

t L'information concernant le port doit aussi être fourni à la commande bind( ), ainsi que l'adresse IP de la machine où se trouve le registre. Mais il faut mentionner que cela peut être un problème frustrant en cas de tests de programmes RMI en local (de la même manière que les programmes réseau testés plus loin dans ce chapitre). En effet dans le JDK version 1.1.1, il y a quelques problèmes : [69]
t t t

  1. localhost
    does not work with RMI. Thus, to experiment with RMI on a single machine,
    you must provide the name of the machine. To find out the name of your machine
    under 32-bit Windows, go to the control panel and select “Network.”
    Select the “Identification” tab, and you’ll see your computer
    name. In my case, I called my computer “Peppy.” It appears that
    capitalization is ignored.


  2. RMI will not work unless
    your computer has an active TCP/IP connection, even if all
    your components are just talking to each other on the local machine. This means
    that you must connect to your Internet service provider before trying to run the
    program or you’ll get some obscure exception messages.


t
  1. localhost ne fonctionne pas avec RMI. Aussi, pour faire une expérience avec RMI sur une seule machine, vous devez fournir le nom de la machine. Pour découvrir le nom de votre machine sous Windows 32-bit, allez dans le Panneau de configuration et sélectionnezRéseau. Sélectionnez l'onglet Identification, vous verrez apparaître le nom de l'ordinateur. Dans mon cas, j'ai appelé mon ordinateur Peppy. Il semble que la différence entre majuscules et minuscules soit ignorée.
  2. RMI ne fonctionnera pas à moins que votre ordinateur ait une connexion TCP/IP active, même si tous vos composants discutent entre eux sur la machine locale. Cela signifie que vous devez vous connecter à Internet pour essayer de faire fonctionner le programme ou vous obtiendrez quelques messages d'exception obscurs.
t t t
With all this in mind, the
bind( ) command becomes:

t En ayant tout cela à l'esprit, la commande bind( ) devient :
t t t
Naming.bind("//peppy:2005/PerfectTime", pt);
t
Naming.bind("//peppy:2005/PerfectTime", pt);
t t t
If you are using the default port 1099,
you don’t need to specify a port, so you could say:

t Si vous utilisez le port par défaut 1099, nul besoin de préciser le port, donc vous pouvez dire :
t t t
Naming.bind("//peppy/PerfectTime", pt);
t
Naming.bind("//peppy/PerfectTime", pt);
t t t
You should be able to perform local
testing by leaving off the IP address and using only the
identifier:

t Vous devriez être capable de réaliser un test local en omettant l'adresse IP et en utilisant simplement l'identifiant :
t t t
Naming.bind("PerfectTime", pt);
t
Naming.bind("PerfectTime", pt);
t t t
The name for the service is arbitrary; it
happens to be PerfectTime here, just like the name of the class, but you could
call it anything you want. The important thing is that it’s a unique name
in the registry that the client knows to look for to procure the remote object.
If the name is already in the registry, you’ll get an
AlreadyBoundException. To
prevent this, you can always use
rebind( )
instead of bind( ), since rebind( ) either adds a new
entry or replaces the one that’s already there.
t Le nom pour le service est arbitraire ; il se trouve que c'est PerfectTime ici, comme le nom de la classe, mais un tout autre nom conviendrait. L'important est que ce nom soit unique dans le registre, connu par le client pour qu'il puisse se procurer l'objet distant. Si le nom est déjà utilisé dans le registre, celui renvoie une AlreadyBoundException. Pour éviter cela, il faut passer à chaque fois par un appel à rebind( ) à la place de bind( ), en effet rebind( ) soit ajoute une nouvelle entrée, soit remplace celle existant déjà.
t t t
Even though main( ) exits,
your object has been created and registered so it’s kept alive by the
registry, waiting for a client to come along and request it. As long as the
rmiregistry is running and you don’t call
Naming.unbind( )
on your
name, the object will be there. For this reason, when you’re developing
your code you need to shut down the rmiregistry and restart it when you
compile a new version of your remote object.
t Durant l'exécution de main( ), l'objet a été créé et enregistré, il reste ainsi en activité dans le registre, attendant qu'un client arrive et fasse appel à lui. Tant que rmiregistry fonctionne et que Naming.unbind( ) n'est pas appelé avec le nom choisi, l'objet sera présent. C'est pour cela que lors de la conception du code, il faut redémarrer rmiregistry après chaque compilation d'une nouvelle version de l'objet distant.
t t t
You aren’t forced to start up
rmiregistry as an external process. If you know that your application is
the only one that’s going to use the registry, you can start it up inside
your program with the line:

t rmiregistry n'est pas forcément démarré en tant que processus externe. S'il est sûr que l'application est la seule qui utilise le registre, celui peut être mis en fonction à l'intérieur même du programme grâce à cette ligne :
t t t
LocateRegistry.createRegistry(2005);
t
LocateRegistry.createRegistry(2005);
t t t
Like before, 2005 is the port number we
happen to be using in this example. This is the equivalent of running
rmiregistry 2005 from a command line, but it can often be more convenient
when you’re developing RMI code since it eliminates the extra steps of
starting and stopping the registry. Once you’ve executed this code, you
can bind( ) using Naming as
before.

t Comme auparavant, nous utilisons le numéro de port 2005 dans cet exemple. C'est équivalent au fait de lancer rmiregistry 2005 depuis la ligne de commande, mais c'est souvent plus pratique lorsque l'on développez son code RMI puisque cela élimine les étapes supplémentaires qui consistent à arrêter et redémarrer le registre. Une fois cette instruction exécutée, la méthode bind( ) de la classe Naming peut être utilisée comme précédemment.
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel