Java RMI - Exemple d’objets distribués

Distributed<em>object</em>communication

__Image Source:

Dans le lien://java/exemple-java-rmi-bonjour-monde/[exemple Java RMI Bonjour Monde], nous avons présenté le https://en.wikipedia.org/wiki/Java remote method invocation[Java Remote Method Invocation]avec une base Communication à base de chaînes entre serveur-client. Dans cet exemple, nous allons un peu plus loin et introduisons la communication serveur-client en utilisant https://en.wikipedia.org/wiki/Distributed object[Objets distribués].

1. L’interface distante

Nous allons d’abord développer la Interface distante qui contient toutes les méthodes implémentées par le serveur. Interface doit toujours être` public` et étendre Remote . Toutes les méthodes décrites dans Remote Interface doivent répertorier` RemoteException` dans leur clause throws.

RMIInterface.java

package com.techfou.rmiinterface;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;

public interface RMIInterface extends Remote {

    Book findBook(Book b) throws RemoteException;
    List<Book> allBooks() throws RemoteException;

}

2. La classe d’objets distribués

Il s’agit de la classe de l’objet que le serveur et le client échangeront et doit implémenter l’interface sérialisable. Il est également extrêmement important que cette classe déclare une valeur explicite serialVersionUID afin de garantir la cohérence entre différentes implémentations du compilateur java.

Si nous l’ignorons ou si la classe d’objets distribués du serveur déclare un serialVersionUID différent de la classe d’objets distribués du client, le processus de désérialisation aboutira à une exception` InvalidClassException`.

Sur Eclipse IDE, vous pouvez générer un serialVersionUID comme ceci:

java-rmi- distributions-objets-exemple-1

Book.java

package com.techfou.rmiinterface;

import java.io.Serializable;

public class Book implements Serializable {

    private static final long serialVersionUID = 1190476516911661470L;
    private String title;
    private String isbn;
    private double cost;

    public Book(String isbn) {
        this.isbn = isbn;
    }

    public Book(String title, String isbn, double cost) {
        this.title = title;
        this.isbn = isbn;
        this.cost = cost;
    }

    public String getTitle() {
        return title;
    }

    public String getIsbn() {
        return isbn;
    }

    public double getCost() {
        return cost;
    }

    public String toString() {
        return "> " + this.title + " ($" + this.cost + ")";
    }

}

3. Le serveur

Le serveur étend UnicastRemoteObject et implémente le` RMIInterface`. Dans la méthode principale, nous lions le serveur sur localhost avec le nom «MyBookstore». Pour plus de simplicité au lieu d’utiliser une base de données ou un "fichier", nous avons créé la méthode initializeList () qui remplit une liste avec des` objets de type livre` représentant les livres que notre librairie a (…​

oui seulement 5. Mais 5 livres géniaux!).

Nous devons également ajouter un serialVersionUID pour le serveur, mais comme le serveur que nous avons conçu dans cet exemple ne doit exister que sur une machine, nous n’avons pas besoin d’y réfléchir deux fois, nous pouvons simplement définir un` serialVersionUID` par défaut. Si, toutefois, la classe de serveurs était également distribuée, nous devions nous assurer que le serialVersionUID de la classe était le même sur toutes les plates-formes qui l’ont implémentée.

Librairie.java

package com.mkyong.rmiserver;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import com.mkyong.rmiinterface.Book;
import com.mkyong.rmiinterface.RMIInterface;

public class Bookstore extends UnicastRemoteObject implements RMIInterface {

    private static final long serialVersionUID = 1L;
    private List<Book> bookList;

    protected Bookstore(List<Book> list) throws RemoteException {
        super();
        this.bookList = list;
    }

   //The client sends a Book object with the isbn information on it
   //(note: it could be a string with the isbn too)

   //With this method the server searches in the List bookList
   //for any book that has that isbn and returns the whole object
    @Override
    public Book findBook(Book book) throws RemoteException {
        Predicate<Book> predicate = x -> x.getIsbn().equals(book.getIsbn());
        return bookList.stream().filter(predicate).findFirst().get();
    }

    @Override
    public List<Book> allBooks() throws RemoteException {
        return bookList;
    }

    private static List<Book> initializeList() {
        List<Book> list = new ArrayList<>();
        list.add(new Book("Head First Java, 2nd Edition", "978-0596009205", 31.41));
        list.add(new Book("Java In A Nutshell", "978-0596007737", 10.90));
        list.add(new Book("Java: The Complete Reference", "978-0071808552", 40.18));
        list.add(new Book("Head First Servlets and JSP", "978-0596516680", 35.41));
        list.add(new Book("Java Puzzlers: Traps, Pitfalls, and Corner Cases", "978-0321336781", 39.99));
        return list;
    }

    public static void main(String[]args) {
        try {
            Naming.rebind("//localhost/MyBookstore", new Bookstore(initializeList()));
            System.err.println("Server ready");
        } catch (Exception e) {
            System.err.println("Server exception: " + e.getMessage());
        }
    }

}

4. Le client

Le client "recherche" le serveur via "l’objet RMIInterface" qui "recherche" une référence à l’objet distant associé au nom que nous passons en tant que paramètre. Ce que nous venons de décrire est ce que fait Naming.lookup ("//localhost/MyBookstore"); `.

Le reste du code pour le client consiste simplement à créer un exemple de travail que vous pourriez expérimenter avec espoir.

Client.java

package com.mkyong.rmiclient;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.List;
import java.util.NoSuchElementException;

import javax.swing.JOptionPane;

import com.mkyong.rmiinterface.Book;
import com.mkyong.rmiinterface.RMIInterface;

public class Customer {

    private static RMIInterface look__up;

    public static void main(String[]args) throws
            MalformedURLException, RemoteException, NotBoundException {

        look__up = (RMIInterface) Naming.lookup("//localhost/MyBookstore");

        boolean findmore;
        do {

            String[]options = {"Show All", "Find a book", "Exit"};

            int choice = JOptionPane.showOptionDialog(null, "Choose an action", "Option dialog",
                    JOptionPane.DEFAULT__OPTION,
                    JOptionPane.INFORMATION__MESSAGE,
                    null, options, options[0]);

            switch (choice) {

                case 0:
                    List<Book> list = look__up.allBooks();
                    StringBuilder message = new StringBuilder();
                    list.forEach(x -> {
                        message.append(x.toString() + "\n");
                    });
                    JOptionPane.showMessageDialog(null, new String(message));
                    break;
                case 1:
                    String isbn = JOptionPane.showInputDialog("Type the isbn of the book you want to find.");
                    try {
                        Book response = look__up.findBook(new Book(isbn));
                        JOptionPane.showMessageDialog(null, "Title: " +
                                        response.getTitle() + "\n" + "Cost: $" +
                                        response.getCost(),
                                response.getIsbn(), JOptionPane.INFORMATION__MESSAGE);
                    } catch (NoSuchElementException ex) {
                        JOptionPane.showMessageDialog(null, "Not found");
                    }
                    break;
                default:
                    System.exit(0);
                    break;

            }
            findmore = (JOptionPane.showConfirmDialog(null, "Do you want to exit?", "Exit",
                    JOptionPane.YES__NO__OPTION) == JOptionPane.NO__OPTION);
        } while (findmore);
    }
}

5. Comment l’exécuter

5.1 Après avoir créé les quatre fichiers java avec votre IDE préféré ou téléchargé le code ci-dessous, accédez au dossier source comme indiqué ci-dessous.

java-rmi-distributions-objets-exemple-2

5.2 La première chose à faire est de compiler nos sources. Run 1. compileEverything.bat si vous avez téléchargé le code ci-dessous ou ouvrez une fenêtre de commande dans votre répertoire et exécutez:

Terminal

$ javac src/com/mkyong/rmiinterface/RMIInterface.java src/com/mkyong/rmiinterface/Book.java src/com/mkyong/rmiserver/Bookstore.java src/com/mkyong/rmiclient/Customer.java

5.3 Confirmez que vos sources ont été compilées en accédant à leurs répertoires respectifs:

java-rmi-distributions-objets-exemple-3

5.4 Ensuite, nous devons commencer la chimie. Encore une fois soit exécuter le 2. startServer.bat ou ouvrez une fenêtre de commande et exécutez:

Terminal

$ cd src
$ start rmiregistry
$ java com.mkyong.rmiserver.Bookstore

java-rmi-distributions-objets-exemple-4

5.5 Si RmiRegistry a démarré avec succès, une autre fenêtre ressemblant à ceci:

java-rmi-distributions-objets-exemple-5

5.6 Nous sommes maintenant prêts à exécuter notre client:

Ouvrez une nouvelle fenêtre d’invite de commande (ou exécutez le fichier 3. runClient.bat à partir des fichiers téléchargés) et exécutez ceci:

Terminal

$ cd src
$ java com.mkyong.rmiclient.Customer

5.6.1 La classe client s’exécute et nous invite à l’action:

java-rmi-distributions-objets-exemple-6

5.6.2 Lorsque nous cliquons sur le bouton “Afficher tout”:

java-rmi-distributions-objets-exemple-7

5.6.3 Après avoir cliqué sur le bouton “OK”:

java-rmi-distributions-objets-exemple-8

5.6.4 Nous cliquons sur le bouton “Non”, car nous ne voulons pas encore quitter et la boîte de dialogue suivante apparaît. Nous tapons un ISBN (ex. «978-0596009205») et cliquez sur «OK».

java-rmi-distributions-objets-exemple-9

5.6.5 Si le livre a été trouvé dans la liste du serveur:

java-rmi-distributions-objets-exemple-10

5.6.6 S’il n’a pas été trouvé:

java-rmi-distributions-objets-exemple-11

5.6.7 Le programme continuera en nous demandant:

java-rmi-distributions-objets-exemple-8

Si nous cliquons sur le bouton “Oui”, le programme se fermera. Si nous cliquons sur «Non», nous reviendrons au menu principal pour choisir une action, comme indiqué en 5.6.1.

Le serveur continuera à fonctionner jusqu’à la fermeture de sa fenêtre. Même après la fermeture du client, nous pouvons en ouvrir un nouveau ou même plusieurs clients exécutés simultanément.

Télécharger le code source

Téléchargement - lien://wp-content/uploads/2017/01/RMIObjects.zip[RMIObjects.zip](5 KB)

Références

Exemple]. https://en.wikipedia.org/wiki/Java remote method__invocation[Wikipedia

Objets distribués]

lien://étiquette/objet distribué/[objet distribué]lien://étiquette/rmi/[rmi]