IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Penser en Java 2nde édition - Sommaire |  Préface |  Avant-propos | Chapitre : 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 |  Annexe : A B C D  | Tables des matières - Thinking in Java

  Chapitre 15 - Informatique distribuée

pages : 1 2 3 4 5 6 7 8 9 10 11 12 

Un CMP Entity Bean a sa persistence assurée par le conteneur d'EJBs. A travers les attributs spécifiés dans le descripteur de déploiement, le conteneur d'EJBs fera correspondre les attributs de l'Entity Bean avec un stockage persistant (habituellement, mais pas toujours, une base de données). La gestion de la persistence par le conteneur réduit le temps de développement et réduit considérablement le code nécessaire pour l'EJB.

Gestion de la persistence par le Bean (BMP - Bean Managed Persistence)

Un BMP Entity Bean a sa persistence implémentée par le fournisseur de l'Entreprise Bean. Le fournisseur d'Entity Bean a en charge d'implémenter la logique nécessaire pour créer un nouvel EJB, mettre à jour certains attributs des EJBs, supprimer un EJB et trouver un EJB dans le stockage persistence. Cela nécessite habituellement d'écrire du code JDBC pour interagir avec une base de données ou un autre stockage persistant. Avec la gestion de persistence par le Bean (BMP), le développeur a le contrôle total de la manière dont la persistence de l'Entity Bean est réalisée.

Le principe de BMP apporte aussi de la flexibilité là où l'implémentation en CMP n'est pas possible, par exemple si vous souhaitez créer un EJB qui encapsule du code d'un système mainframe existant, vous pouvez écrire votre persistence en utilisant CORBA.

Développer un Enterprise Java Bean

Nous allons maintenant implémenter l'exemple de Perfect Time de la précédente section à propos de RMI sous forme d'un composant Entreprise JavaBean. Cet exemple est un simple Session Bean non-persistant. Les composants Enterprise JavaBean représenteront toujours au moins à une classe et deux interfaces.

La première interface définie est l'interface Remote de notre composant Enterprise JavaBean. Lorsque vous créez votre interface Remote de votre EJB, vous devez suivre ces règles :

  1. L'interface Remote doit être public.
  2. L'interface Remote doit hériter de l'interface javax.ejb.EJBObject.
  3. Chaque méthode de l'interface Remote doit déclarer java.rmi.RemoteException dans sa section throws en addition des exceptions spécifiques à l'application.
  4. Chaque objet passé en argument ou retourné par valeur (soit directement soit encapsulé dans un objet local) doit être un type de donnée valide pour RMI-IIOP (ce qui inclut les autres objets EJB).

Voici l'interface Remote plutôt simple de notre EJB PerfectTime :

//: c15:ejb:PerfectTime.java
//# Vous devez installer le J2EE Java Enterprise
//# Edition de java.sun.com et ajouter j2ee.jar
//# à votre CLASSPATH pour pouvoir compiler
//# ce fichier. Pour plus de détails,
//# reportez vous au site java.sun.com.
//# Interface Remote de PerfectTimeBean
import java.rmi.*;
import javax.ejb.*;

public interface PerfectTime extends EJBObject {
  public long getPerfectTime()
    throws RemoteException;
} ///:~

La seconde interface définie est l'interface Home de notre composant Enterprise JavaBeans. L'interface Home est la Factory du composant que vous allez créer. L'interface Home peut définir des méthodes de création ou de recherche. Les méthodes de création créent les instances des EJBs, les méthodes de recherche localisent les EJBs existants et sont utilisés pour les Entity Beans seulement. Lorsque vous créez votre interface Home d'un EJB, vous devez respecter ces quelques règles :

  1. L'interface Home doit être public.
  2. L'interface Home doit hériter de l'interface javax.ejb.EJBHome.
  3. Chaque méthode de l'interface Home doit déclarer java.rmi.RemoteException dans sa section throws de même que javax.ejb.CreateException
  4. La valeur retournée par une méthode de création doit être une interface Remote.
  5. La valeur retournée par une méthode de recherche (pour les Entity Beans uniquement) doit être une interface Remote, java.util.Enumeration ou java.util.Collection.
  6. Chaque objet passé en argument ou retourné par valeur (sous directement ou encapsulé dans un objet local) doit être un type de donnée valide pour RMI-IIOP (ce qui inclut les autres objets EJB).

La convention standard de nommage des interfaces Home consiste à prendre le nom de l'interface Remote et d'y ajouter à la fin Home. Voici l'interface Home de notre EJB PerfectTime :

//: c15:ejb:PerfectTimeHome.java
// Interface Home de PerfectTimeBean.
import java.rmi.*;
import javax.ejb.*;

public interface PerfectTimeHome extends EJBHome {
  public PerfectTime create()
    throws CreateException, RemoteException;
} ///:~

Maintenant que nous avons défini les interfaces de notre composant, nous pouvons implémenter la logique métier qu'il y a derrière. Lorsque vous créez la classe d'implémentation de votre EJB, vous devez suivre ces règles (notez que vous pourrez trouver dans la spécification des EJBs la liste complète des règles de développement des Entreprise JavaBeans) :

  1. La classe doit être public.
  2. La classe doit implémenter une interface (soit javax.ejb.SessionBean, soit javax.ejb.EntityBean).
  3. La classe doit définir les méthodes correspondant aux méthodes de l'interface Remote. Notez que la classe n'implémente pas l'interface Remote, c'est le miroir des méthodes de l'interface Remote mais elle n'émet pas java.rmi.RemoteException.
  4. Définir une ou plusieurs méthodes ejbCreate( ) qui initialisent votre EJB.
  5. La valeur retournée et les arguments de toutes les méthodes doivent être des types de données compatibles avec RMI-IIOP.

//: c15:ejb:PerfectTimeBean.java
// Un Session Bean non-persistant
// qui retourne l'heure système courante.
import java.rmi.*;
import javax.ejb.*;

public class PerfectTimeBean
  implements SessionBean {
  private SessionContext sessionContext;
  // retourne l'heure courante
  public long getPerfectTime() {
     return System.currentTimeMillis();
  }
  // méthodes EJB
  public void
  ejbCreate() throws CreateException {}
  public void ejbRemove() {}
  public void ejbActivate() {}
  public void ejbPassivate() {}
  public void
  setSessionContext(SessionContext ctx) {
    sessionContext = ctx;
  }
}///:~

Notez que les méthodes EJB (ejbCreate( ), ejbRemove( ), ejbActivate( ), ejbPassivate( ) ) sont toutes vides. Ces méthodes sont appelées par le conteneur d'EJBs et sont utilisées pour contrôler l'état de votre composant. Comme c'est un exemple simple, nous pouvons les laisser vide. La méthode setSessionContext( ) transmet un objet javax.ejb.SessionContext qui contient les informations concernant le contexte dans lequel se trouve le composant, telles que la transaction courante et des informations de sécurité.

Après que nous ayons créé notre Enterprise JavaBean, nous avons maintenant besoin de créer le descripteur de déploiement. Dans les EJBs 1.1, le descripteur de déploiement est un fichier XML qui décrit le composant EJB. Le descripteur de déploiement doit être stocké dans un fichier appelé ejb-jar.xml.

<?xml version="1.0" encoding="Cp1252"?>
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN' 'http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd'>

<ejb-jar>
  <description>Exemple pour le chapitre 15</description>
  <display-name></display-name>
  <small-icon></small-icon>
  <large-icon></large-icon>
  <enterprise-beans>
    <session>
      <ejb-name>PerfectTime</ejb-name>
      <home>PerfectTimeHome</home>
      <remote>PerfectTime</remote>
      <ejb-class>PerfectTimeBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
    </session>
  </enterprise-beans>
  <ejb-client-jar></ejb-client-jar>
</ejb-jar>

Dans la balise <session> de votre descripteur de déploiement, vous pouvez voir que le composant, les interfaces Remote et Home sont définis en partie. Les descripteurs de déploiement peuvent facilement être générés automatiquement grâce à des outils tels que JBuilder.

Par l'intermédiaire de ce descripteur de déploiement standard ejb-jar.xml, la spécification des EJBs 1.1 institue que toutes balises spécifiques aux fournisseurs doivent être stockées dans un fichier séparé. Ceci a pour but d'assurer une compatibilité complète entre les composants et les conteneurs d'EJBs de différents marques.

Maintenant que nous avons créé notre composant et défini sa composition dans le descripteur de déploiement, nous devons alors archiver les fichiers dans un fichier archive Java (JAR). Le descripteur de déploiement doit être placé dans le sous répertoire META-INF du fichier Jar.

Une fois que nous avons défini notre composant EJB dans le descripteur de déploiement, le déployeur doit maintenant déployer le composant EJB dans le conteneur d'EJB. A ce moment-là du développement, le processus est plutôt orienté IHM et spécifique à chaque conteneur d'EJBs. Nous avons donc décidé de ne pas documenter entièrement le processus de déploiement dans cette présentation. Chaque conteneur d'EJBs propose cependant à un processus détaillé pour déployer un EJB.

Puisqu'un composant EJB est un objet distribué, le processus de déploiement doit créer certains stubs clients pour appeler le composant EJB. Ces classes seront placées dans le classpath de l'application cliente. Puisque les composants EJB sont implémentés par dessus RMI-IIOP (CORBA) ou RMI-JRMP, les stubs générés peuvent varier entre les conteneurs d'EJBs, néanmoins ce sont des classes générées.

Lorsqu'un programme client désire invoquer un EJB, il doit rechercher le composant EJB dans JNDI et obtenir une référence vers l'interface Home du composant EJB. L'interface HOME peut alors être invoquée pour créer une instance de l'EJB, qui peut à son tour être invoquée.

Dans cet exemple le programme client est un simple programme Java, mais vous devez garder en mémoire qu'il pourrait s'agir aussi bien d'un Servlet, d'un JSP que d'un objet distribué CORBA ou RMI.

Le code de PerfectTimeClient code est le suivant.

//: c15:ejb:PerfectTimeClient.java
// Programme Client pour PerfectTimeBean

public class PerfectTimeClient {
public static void
main(String[ « args) throws Exception {
  // Obtient un context JNDI utilisant le
  // service de nommage JNDI :
  javax.naming.Context context =    new javax.naming.InitialContext();
  // Recherche l'interface Home dans le
  // service de nommage JNDI :
  Object ref = context.lookup("perfectTime");
  // Transforme l'objet distant en une interface Home :
  PerfectTimeHome home = (PerfectTimeHome)
    javax.rmi.PortableRemoteObject.narrow(
      ref, PerfectTimeHome.class);
  // Crée un objet distant depuis l'interface Home :
  PerfectTime pt = home.create();
  // Invoque  getPerfectTime()
  System.out.println(
    "Perfect Time EJB invoked, time is: " +
    pt.getPerfectTime() );
  }
} ///:~

Le déroulement de cet exemple est expliqué dans les commentaires. Notez l'utilisation de la méthode narrow() pour réaliser une sorte de transtypage de l'objet avant qu'un transtypage Java soit fait. Ceci est très similaire à ce qui se passe en CORBA. Notez aussi que l'objet Home devient une Factory pour les objets PerfectTimes.

En résumé

La spécification des Enterprise JavaBeans est un pas important vers la standardisation et la simplification de l'informatique distribuée. C'est une pièce majeure de Java 2, Enterprise Edition Platform et reçoit en plus le concours la communauté travaillant sur les objets distribués. De nombreux outils sont actuellement disponibles ou le seront dans un futur proche pour accélérer le développement de composants EJBs.

Cette présentation avait pour but de donner un bref aperçu de ce que sont les EJBs. Pour plus d'informations à propos de la spécification des Enterprise JavaBeans, vous pouvez vous reporter à la page officielle des Enterprise JavaBeans à l'adresse http://java.sun.com/products/ejb/. Vous pourrez y télécharger la dernière spécification ainsi que Java 2, Enterprise Edition Reference Implementation, qui vous permettra de développer et de déployer vos propres composants EJBs.

Jini : services distribués

Cette section [71]donne un aperçu de la technologie Jini de Sun Microsystem. Elle décrit quelques spécificités Jini et montre comment l'architecture Jini aide à augmenter le niveau d'abstraction dans la programmation de systèmes distribués, transformant réellement la programmation réseau en programmation orientée-objets.

Contexte de Jini

Traditionnellement, les systèmes d'exploitation sont conçus dans l'hypothèse qu'un ordinateur aura un processeur, un peu de mémoire et un disque. Lorsque vous démarrez votre ordinateur, la première chose qu'il fait est de chercher un disque. S'il ne le trouve pas, il ne peut assurer sa fonction d'ordinateur. Cependant de plus en plus les ordinateurs apparaissent sous diverses formes : comme des systèmes embarqués qui possèdent un processeur, un peu de mémoire et une connexion réseau mais pas de disque. La première chose que fait, par exemple, un téléphone cellulaire lorsqu'il s'allume est de rechercher le réseau téléphonique. S'il ne le trouve pas, il ne peut assurer sa fonction de téléphone. Cette nouvelle mode dans l'environnement matériel, le passage d'un système centré sur un disque à un système centré sur un réseau, va affecter la manière d'organiser notre logiciel. C'est là qu'intervient Jini.

Jini est une manière de repenser l'architecture de l'ordinateur, étant donné l'importance croissante des réseaux et la prolifération des processeurs dans des systèmes qui n'ont pas de disque dur. Ces systèmes, qui proviennent de nombreux fabricants différents, vont avoir besoin d'interagir à travers le réseau. Le réseau lui-même sera très dynamique : les systèmes et les services seront ajoutés et retirés régulièrement. Jini apporte les mécanismes permettant facilement l'ajout, la suppression et la recherche de systèmes et de services sur le réseau. De plus, Jini propose un modèle de programmation qui rend tout cela plus facile pour les programmeurs qui souhaitent voir leurs systèmes discuter entre eux.

S'appuyant sur Java, la sérialisation objet et RMI (qui permet aux objets de bouger à travers le réseau en passant d'une machine virtuelle à une autre), Jini permet d'étendre les bénéfices de la programmation orientée-objet au réseau. Au lieu de nécessiter un accord entre les différents fabricants sur un protocole réseau à travers lequel les systèmes peuvent interagir, Jini permet à ces systèmes de discuter ensemble par l'intermédiaire d'interfaces vers des objets.

Qu'est-ce que Jini ?

Jini est un ensemble d'APIs et de protocoles réseaux qui peuvent vous aider à construire et déployer des systèmes distribués qui sont organisés sous la forme de fédérations de services . Un service peut être n'importe quoi qui se trouve sur le réseau et qui est prêt à réaliser une fonction utile. Des composants matériels, logiciels, des canaux de communications, les utilisateurs eux-mêmes peuvent être des services. Une imprimante compatible Jini pourra offrir un service d'impression. Une fédération de services est un ensemble de services, actuellement disponibles sur le réseau, que le client (ce qui signifie programme, service ou utilisateur) peut combiner pour s'aider à atteindre à son but.

Pour réaliser une tâche, un client enchaîne les possibilités des services. Par exemple, un programme client peut charger des photographies d'un système de stockage d'image d'un appareil numérique, envoyer les photos vers un service de stockage persistant offert par un disque dur, et transmettre une page contenant les vignettes de chaque image à un service d'impression d'une imprimante couleur. Dans cet exemple, le programme client construit un système distribué constitué de lui-même, le service de stockage d'images, le service de stockage persistant et le service d'impression couleur. Le client et ces services de ce système distribué collaborent pour réaliser une tâche : décharger et stocker les images d'un appareil numérique et imprimer une page de vignettes.

L'idée derrière le mot fédération est que la vision Jini d'un réseau n'instaure pas d'autorité de contrôle centrale. Puisque aucun service n'est responsable, l'ensemble de tous les services disponible sur le réseau forme une fédération, un groupe composé de membres égaux. Au lieu d'une autorité centrale, l'infrastructure d'exécution de Jini propose un moyen pour les clients et les services de se trouver mutuellement (à travers un service de recherche, qui stocke la liste des services disponibles à moment donné). Après que les services se sont trouvés, ils sont indépendants. Le client et ces services mis à contribution réalisent leurs tâches indépendamment de l'infrastructure d'exécution de Jini. Si le service de recherche Jini tombe, tous les systèmes distribués mis en place par le service de recherche, avant qu'il ne plante, peuvent continuer les travaux. Jini incorpore même un protocole réseau qui permet aux clients de trouver les services en l'absence d'un service de nommage.

Comment fonctionne Jini

Jini définie une infrastructure d'exécution qui réside sur le réseau et met à disposition des mécanismes qui vous permettent d'ajouter, d'enlever, de localiser et d'accéder aux services. L'infrastructure d'exécution se situe à trois endroits : dans les services de recherche qui sont sur le réseau, au niveau des fournisseurs de service (tels que les systèmes supportant Jini), et dans les clients. Les services de recherche forment le mécanisme centralisé d'organisation des systèmes basés sur Jini. Lorsque des services deviennent disponibles sur le réseau, ils s'enregistrent eux-même grâce à un service de recherche. Lorsque des clients souhaitent localiser un service pour être assistés dans leur travail, ils consultent le service de recherche.

L'infrastructure d'exécution utilise un protocole au niveau réseau, appelé discovery (découverte), et deux protocoles au niveau objet appelés join (joindre) et lookup (recherche). Discovery permet aux clients et aux services de trouver les services de recherche. Join permet au service de s'enregistrer lui-même auprès du service de recherche. Lookup permet à un client de rechercher des services qui peuvent l'aider à atteindre ses objectifs.

Le processus de découverte

Le processus de découverte travaille ainsi : imaginez un disque supportant Jini et offrant un service de stockage persistant. Dès que le disque est connecté au réseau, il diffuse une annonce de présence en envoyant un paquet multicast sur un port déterminé. Dans l'annonce de présence, sont inclus une adresse IP et un numéro de port où le disque peut être contacté par le service de recherche.

Les services de recherche scrutent sur le port déterminé les paquets d'annonce de présence. Lorsqu'un service de recherche reçoit une annonce de présence, il l'ouvre et inspecte le paquet. Le paquet contient les informations qui permet au service de recherche de déterminer s'il doit ou non contacter l'expéditeur de ce paquet. Si tel est le cas, il contacte directement l'expéditeur en établissant une connexion TCP à l'adresse IP et sur le numéro de port extraits du paquet. En utilisant RMI, le service de recherche envoie à l'initiateur du paquet un objet appelé un enregistreur de service (service registrar). L'objectif de cet enregistreur de service est de faciliter la communication future avec le service de recherche. Dans le cas d'un disque dur, le service de recherche attablirait une connexion TCP vers le disque dur et lui enverrait un enregistreur de service, grâce auquel le disque dur pourra faire enregistrer son service de stockage persistant par le processus de jonction.

Ce livre a été écrit par Bruce Eckel ( télécharger la version anglaise : Thinking in java )
Ce chapitre a été traduit par Jean-Pierre Vidal, Alban Peignier ( groupe de traduction )
télécharger la version francaise (PDF) | Commandez le livre en version anglaise (amazon) | télécharger la version anglaise
pages : 1 2 3 4 5 6 7 8 9 10 11 12 
Penser en Java 2nde édition - Sommaire |  Préface |  Avant-propos | Chapitre : 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 |  Annexe : A B C D  | Tables des matières - Thinking in Java