Vous êtes sur la page 1sur 73

Evénements

Java Beans
Java RMI
X. BLANC & J. DANIEL
Xavier.Blanc@lip6.fr , Jerome.Daniel@der.edf.fr
Les événements dans Java

X. BLANC & J. DANIEL


Xavier.Blanc@lip6.fr , Jerome.Daniel@der.edf.fr
Le modèle événementiel

• Les événements sont un moyen de communication


alternatif entre deux objets.
• Les communications par événements sont asynchrones.
Un objet lance un événement et un autre objet attrape
cet événement.
• Exemples d’événements : click de sourie, changement
d’une base de donnée …
Le modèle événementiel
Le modèle événementiel

Le modèle événement de Java est tout objet.


• Le lanceur d’événement est un objet
• Le receveur d’événement est un objet
• L’événement est un objet.
Exemple d'événement

• La classe JButton est capable de lancer l’événement


java.awt.Event.ActionEvent
Cet événement est lancé lorsque l’on clique sur un bouton.
• Les classes capables de recevoir cet événement doivent implanter
l’interface
java.awt.event.ActionListener
• Pour qu’un receveur (listener) se connecte à un lanceur, il doit
appeler la méthode
addActionListener()
du lanceur.
• Lorsque le lanceur lance un événement, il appelle les méthodes
actionPerformed(ActionEvent e)
de l ’interface ActionListener
Exemple d’événement

// la classe receveur
public class MonListener implements java.awt.event.ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println(“evenement recu !”);
}
}

// quelque part dans le programme, le lien entre le receveur et le lanceur
java.swing.JButton button = new java.swing.JButton(“click”);

button.addActionListener(new MonListener());
Le Lanceur d’événements

• Un objet qui lance des événements doit proposer des


méthodes pour que des receveurs puissent d’enregistrer.
Ces méthodes sont toujours sous la forme
addXXXListener()
Où XXX est le type d’événement lancé.
• Lorsqu’il jette un événement, le lanceur le jette vers
tout les objets qui se sont enregistrés.
• Les méthodes
removeXXXListener()
Permettent de ne plus enregistrer des objets.
L'événement

• Les événements doivent tous hériter de la classe


java.util.Event
• Cette classe dispose de deux méthodes
– public String toString()
Cette méthode donne une représentation de l ’événement sous
forme de chaîne de caractère (inintéressant).
– public Object getSource()
Cette méthode donne une référence vers l’objet qui a crée cet
événement (très intéressant)
Le receveur d’événements

• Le receveur d’événement doit implanter l’interface


correspondant à l’événement.
XXXListener
• Cette interface contient les méthodes appelées lorsque
l’évenement est jeté.
• Toutes ces interfaces héritent de l’interface
java.util.EventListener
Cette interface n’a aucune méthode.
Architecture

• Il y a différents choix d’architecture possibles.


– Soit une classe qui centralise tous les événements. Cette classe
est le recepteur, elle implante toute les interface Listener.
– Soit plusieurs classes receveur. Chaque receveur est lié avec un
certain nombre de lanceur.
– Soit une classe interne pour chaque événement.
ActionListener

Cette interface doit être implantée par les receveurs


d’événement Action
• public void actionPerformed(ActionEvent e)
est la seule méthode de cette interface.
• ActionEvent est l’objet représentant un événement de type
action.
• Ces événements sont jetés par les Button, List, Menu, ...
WindowListener

Cette interface doit être implantée par les receveurs


d’événement Window
• public void windowActivated(WindowEvent e)
public void windowClosed(WindowEvent e)
public void windowIconified(WindowEvent e)
...
Sont des méthodes de cette interface.
• WindowEvent est l’objet représentant un événement de type
window.
• Ces événements sont jeté par les Window, Frame ...
MouseListener

Cette interface doit être implantée par les receveurs


d’événement Mouse
• public void mousePressed(MouseEvent e)
public void mouseClicked(MouseEvent e)
public void mouseExited(MouseEvent e)
...
Sont des méthodes de cette interface.
• MouseEvent est l’objet représentant un événement de type
mouse.
• Ces événements sont jeté par les Window, Button, ...
MouseMotionListener

Cette interface doit être implantée par les receveurs


d’événement MouseMotion
• public void mouseDragged(MouseEvent e)
public void mouseMoved(MouseEvent e)
...
Sont des méthodes de cette interface.
• MouseEvent est l’objet représentant un événement de type
sourie.
• Ces événements sont jeté par les Component, Button, ...
KeyListener

Cette interface doit être implantée par les receveurs


d’événement Key
• public void keyPressed(KeyEvent e)
public void keyReleased(KeyEvent e)
...
Sont des méthodes de cette interface.
• KeyEvent est l’objet représentant un événement de type
key.
• Ces événements sont jeté par les List, Button, Frame ...
FocusListener

Cette interface doit être implantée par les receveurs


d’événement Focus
• public void focusGained(FocusEvent e)
public void FocusLost(FocusEvent e)
...
Sont des méthodes de cette interface.
• FocusEvent est l’objet représentant un événement de type
focus.
• Ces événements sont jeté par les Component, Button, ...
AdjustmentListener

Cette interface doit être implantée par les receveurs


d’événement Adjustement
• public void adjustmentValueChanged(AdjustmentEvent e)
est la seule méthode de cette interface.
• AdjustmentEvent est l’objet représentant un événement de
type adjustment.
• Ces événements sont jeté par les Scrollbar ...
Les Adapter

• Lorsque l’on veut créer un Listener il faut que la classe


du listener implante toutes les méthodes de l’interface.
• Cependant, il n’est pas dit que toutes les méthodes nous
intéresse.
• Ex : WindowListener (iconified, closed …)
• Les classes Adapter sont des classes abstraites qui
implantent les interface Listener.
Exemple : MouseAdapter

• La classe java.awt.event.MouseAdapter implante


l’interface MouseListener
• Ainsi pour créer un recepteur de MouseEvent, il suffit
de créer une classe qui hérite de MouseAdapter.
• Les autres adapter :
– KeyAdapter
– MouseAdpter
– WindowAdapter
– ContainerAdapter
– ...
Construire ses événements

• Le modèle événementiel de Java n’est qu’une


architecture.
• Pour créer ses propres événements il faut
– Créer sa classe événement qui hérite de java.util.Event
– Créer l’interface Listener qui hérite de java.util.EventListener
– Dans la classe lanceur créer les méthode pour inscrire les
receveur.
– Gérer le fait de lancer un événement.
Construire ses événements

• On ne peut pas créer de nouveaux événements


graphiques.
• Le seul moyen est de les utiliser.
• Ou, en hériter.
Exercice

• Construire une classe Pile qui génère un événement de


NewItem dès qu’un nouvel élément est inséré dans la
pile.
Attention ce modèle est celui de AWT 1.1

• Le modèle événementiel présenté ici est celui définie


dans AWT 1.1
• Le modèle événementiel de AWT 1.0 est tout à fait
différent.
• D’où utilisation de jdk1.1.x ou jdk1.2.x
Java Beans

X. BLANC & J. DANIEL


Xavier.Blanc@lip6.fr , Jerome.Daniel@der.edf.fr
Java Beans

• Modèle de Composant
• auto-descriptif
• réutilisable
• principalement visuel
• java
Java Beans

• Construction d’un Beans


– Modèle Beans
– Règles syntaxiques
– Pacquage
• Déploiement d’un Beans
– Utilisation d’outils graphiques
• Exécution d’un Beans
– programme classique
Construction d’un Beans

Modèle Beans et Règles de syntaxes


Modèle Beans

• Un Bean est une classe


• Cette classe doit être conforme au modèle Beans
• Ce modèle permet aux outils de découvrir les Beans
• Un Bean encapsule sa propre description
=>Propriété générale des COMPOSANTS
Modèle Beans

• Un Beans est une classe Java


• Implante l’interface java.io.Serializable
• Fournir un constructeur public sans argument
• Possède des propriétés
• Peu envoyer des événements
Propriétés du Bean

• Un Beans possède des propriétés


• Les propriétés d’un Beans sont les aspects du Beans qui
pourront être modifier lors du déploiement du Bean
• Ex: couleurDeFond, typeDeFont ...
Propriétés Simples

• L’accès aux propriétés se fait par des méthodes set /


get.
• Example :
private int toto; // La propriete
public int gettoto() { return toto;} //La syntaxe doit être respectée
public void settoto(int value) { toto=value;} //idem

• Ces règles syntaxiques permettent aux outils de


découvrir les méthodes.
Propriétés Indexées

• Les propriétés indexées


public void setXXX(int index, type value);
public void setXXX(type values[]);
public type getXXX(int index);
public type[] getXXX();
Propriétés Liées

• Les propriétés peuvent être liées: un changement d’une


propriété d’un Beans entraîne un changement d’une
propriété d’un autre Beans.
• Le lien entre deux propriétés est unidirectionnel. Il y a
donc la propriété dépendante et la propriété lié.
• En fait, il y a la propriété lié et le bean qui contient la
propriété dépendante.
• L ’utilisation d’une propriété liée consiste plus
particulièrement à notifier divers événements aux beans
intéresséS.
Propriétés Liées

• Le Beans contenant la propriété liée


import java.beans.*;
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
public void addPropertyChangeListener( PropertyChangeListener l) {
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
changes.removePropertyChangeListener(l);
}
public void setLabel(String newLabel) {
String oldLabel = label;
label = newLabel;
sizeToFit();
changes.firePropertyChange("label", oldLabel, newLabel);
}
Propriétés Liées

• Le Beans contenant la propriété dépendante

public class MyClass implements java.beans.PropertyChangeListener,


java.io.Serializable { …

public void propertyChange(PropertyChangeEvent evt) {…}

...
}
Propriétés Contraintes

• Un propriété de Beans peut être contrainte.


• Les contraintes sont un cas particulier des propriétés
liées, un bean peu émettre un veto sur le changement
d’une propriété contrainte.
• Les mécanismes de propriété contrainte sont similaires
aux propriétés liées.
– Les méthodes set doivent générer l’exception
PropertyVetoException
Propriétés Contraintes

• Le Beans qui contient la propriété contrainte


import java.beans.*;
private VetoableChangeSupport vetos = new VetoableChangeSupport(this);

public void addVetoableChangeListener(VetoableChangeListener l) {


vetos.addVetoableChangeListener(l)}

public void removeVetoableChangeListener(VetoableChangeListener l){


vetos.removeVetoableChangeListener(l);}

public void setPriceInCents(int newPriceInCents) throws PropertyVetoException {


int oldPriceInCents = ourPriceInCents;
vetos.fireVetoableChange("priceInCents",new Integer(oldPriceInCents),
new Integer(newPriceInCents));
ourPriceInCents = newPriceInCents;
changes.firePropertyChange("priceInCents",new Integer(oldPriceInCents),
new Integer(newPriceInCents));
}
Propriétés Contraintes

• Beans émettant le veto


public class MyClass implements VetoableChangeListener interface {
….
void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
….
}
}
Exercice

Créer un Bean possédant les propriétés :


– int a;
– String b;

Puis faite que a soit une propriété contrainte


Communication par événements

• Les Java Beans communique par événements.


• Un bean envoie un événement vers un bean capable de
comprendre ce type d’événement
• Lorsqu’un bean génère des événements, il faut qu’il
possède ces méthodes pour chacun des événements
qu’il est capable de générer.:
– public void add<EventListenerType>(<EventListenerType> a)
– public void remove<EventListenerType>(<EventListenerType a)
Méthodes du bean

• Pour qu’un bean puisse offrir ces services, il faut que


les méthodes soient public.

public type nom_methode(parametre) {…}


Introspection

Comment connaître un Java Bean


Principe

• Un bean est un composant qui va être manipulé par des


outils graphiques.
• Le bean doit donc permettre à ces outils de savoir
comment le bean fonctionne.
• L’introspection permet de connaître les propriétés, les
méthodes et les événements que manipule le bean.
Le package reflect

• Java propose une API pur découvrir une classe lors de


l’exécution.
• Ce qui permet d’exécuter dynamiquement une méthode
sur une classe.
• Le package reflect peut être utilisé pour n ’importe
quelle classe Java, donc aussi pour les bean.
La classe Introspector

• Le package java.beans propose une autre manière de


découvrir une classe
• Cette manière se fait à travers la classe Introspector.
• L’introspection de Java Bean utilise la réflexion mais
aussi les règles syntaxiques de Java Beans
• L’introspection permet aussi d’utiliser la classe
BeanInfo pour décrire un Java Bean
Obtenir la référence vers un BeanInfo

• Si aucun BeanInfo n’a été proposé par le constructeur


de bean, il en sera généré un automatiquement.

MonBean mb = new MonBean();


BeanInfo bi = Introspector.getBeanInfo(mb.getClass());
La classe BeanInfo

• La classe BeanInfo est une interface qui contient toute


les méthodes permettant de connaître un Bean.
• Un objet de type BeanInfo est retourné lors de l’appel à
l’introspector.
• Si, le bean possède un BeanInfo qui lui est propre, cette
objet sera de ce type.
Des méthodes de la classe BeanInfo

• public MethodDescriptor[] getMethodDescriptors()


• public PropertyDescriptor[] getPropertyDescriptors()
• public EventSetDescriptor[] getEventSetDescriptors()
• public BeanDescriptor getBeanDescriptor()
Des méthodes de PropertyDescriptor

• public Class getPropertyType()


• public boolean isConstrained()
• ...
Création d’un BeanInfo

• Le nom de la classe BeanInfo doit être le nom du bean


précédé de BeanInfo
Ex: MonBeanBeanInfo
• Cette classe doit hériter de SimpleBeanInfo
• Re-écrire les méthodes que l’on veut modifier.
Property Editors / Customizers

• Les Beans sont manipulés par un outil graphique. Cet


outil va permettre de saisir les valeurs de bases des
propriétés.
• Les Property Editors permettent de paramètrer la façon
de saisir les informations dans l’outil graphique.
• Les Customizers sont des composants graphiques qui
vont être intégrés dans l’outil pour la saisie des
propriétés.
Exercice

• Proposer une méthode qui prend le nom d’un Bean et


qui affiche à l’écran le nom de toutes les méthodes du
bean.
Déploiement de Beans

Utilisation de la Bean Box


Principe

• Nous avons vu qu’un bean était constitué de plusieurs


classe Java.
• Cependant, ces classes forment un tout : le bean.
• Voilà pourquoi il faut archiver toutes les classes dans
un seul fichier. Un fichier .jar
Le manifest du fichier Jar

• Dans tout archive .jar, il y a un fichier manifest.mnf qui


décrit le contenu de l’archive.
• Pour les Java Beans le manifest doit contenir:
Name: toto.class
Java-Bean: True
Le fichier Jar

• Pour archiver des classes dans un fichier Jar:

jar cfm fichier.jar fichier.mnf liste_fichier

ex:jar cfm toto.jar toto.mnf *.class


Java RMI

X. BLANC & J. DANIEL


Xavier.Blanc@lip6.fr , Jerome.Daniel@der.edf.fr
Principe de Java RMI

• Java RMI pour Java Remote Method Invocation


• C’est un façon pour faire communiquer deux classes
situés sur deux machines différentes.
• Une classe située dans une machine virtuelle appelle la
méthode d’une classe située dans une autre machine
virtuelle.
• Java RMI est une architecture Sun (contrairement à
CORBA
Architecture de Java RMI

Client Serveur

Stub Skeleton
Remote Reference Layer

Transport Layer
Obtention du stub à l’exécution

• Il faut disposer du stub de l’objet pour pouvoir invoquer


des méthodes à distance.
• Si on ne dispose pas du stub, il est possible de l’obtenir
au moment de l’utilisation de l’objet.
– La classe implantant le stub est rechercher en locale
– Si la classe n’est pas trouvée en locale, on la cherche sur le site
distant
– Le stub est transmis au poste client puis chargé par le client
lui-même
• Ce mécanisme est automatiquement géré par Java.
Définir une interface distante Java

• Une interface distante décrit un objet distant. Elle doit


hériter de java.rmi.Remote
• Cette interface identifie le décrit le type des objets
répartis
• Toute les méthodes qui constituent l’interface distante
doivent pouvoir générer une exception de type
RemoteException
Exemple d’interface

Import java.rmi.*;

public interface Calculatrice extends Remote {

public add(int a, int b) throws RemoteException;

}
Implanter une interface

• On définie une classe qui implante l’interface distante.


Cette classe doit hériter de UnicastRemoteObject
import java.rmi.*;
import java.rmi.server.*;
public class CalculatriceImpl extends UnicastRemoteObject Implements Calculatrice {

public int add(int a, int b) throws RemoteException { return a+b;}

}
Rendre accessible un serveur

• Pour cela on doit :


– créer un manager de sécurité
– ajouter le serveur a ceux disponible sous Java RMI (bind)
public static void main(String args[]) {
try {
System.setSecurityManager(new RMISecurityManager());
CalculatriceImpl calc = new CalculatriceImpl();
String nom = "Calculatrice";
Naming.rebind(nom.calc);
}
catch (Exception ex) {…}
}
Générer le stub et le skeleton

• Pour cela, on utilise le compilateur rmic fourni avec


Java.
• Les arguments de rmic sont identiques à ceux de javac
• La génération du stub et du skeleton s ’effectue à partir
de la classe d’implantation
rmic CalculatriceImpl
Développer un client

• Le client est une classe traditionnelle qui va utiliser le


service de désignation de Java RMI pour retrouver le
serveur auquel il souhaite accéder.
• Le service de désignation va retourner une référence sur
l’objet (RemoteObject) qui devra être convertie vers
l’objet que l’on souhaite utiliser (cast).
• L’opération qui retourne le serveur prend en paramètre
une sorte d ’URL (//host/name).
Exemple de client

Import java.rmi.*;

public class CalculatriceClient {


public static void main(String args[]) {
String serverName = "Calculatrice";
CalculatriceInterface calc;
try {
calc = (CalculatriceInterface)
Naming.lookup(serveurName.toString());
System.out.println(" 6+2= "+calc.add(6,2);
}
catch (RemoteException ex) {…}
catch (Exception e) {…}
}
}
Exécuter l’application répartie

• On doit en premier lieux, lancer le service de


désignation de Java RMI (rmiregistry) sur la machine
ou se situ le serveur
• Ce service doit connaître l’endroit où les classes sont
accessibles (c’est à dire que le CLASSPATH doit être
positionné avent le lancement de l’utilitaire.
• On lance ensuite le serveur, puis le client
Exercice

• Créer une classe accessible à distance. Cette classe sera


une pile.
Sérialisation des objets

• La sérialisation est un mécanisme utilisé pour


l’encodage et décodage des paramètres lors d’un appel
distant.
• En particulier, dans le cas ou l’on devrait passer une
structure de données particulière lors d’un appel, notre
structure devrait supporter la notion de sérialisation
pour pouvoir être transmise (c ’est à dire implanter
l’interface java.io.Serializable).
Les exceptions avec Java RMI

• Toutes les méthodes d’une interface doivent signaler


l’exception RemoteException car:
– il peut survenir un problème lors d’une communication
client/serveur : dans ce cas, c’est RMI qui généra cette
exception.
• Toutes les exceptions définies par l’utilisateur devront
hériter de la classe RemoteException.
Garbage collector d’objets distants

• De façon à maintenir une cohérence dans la modèle Java. Java


RMI dispose d’un mécanisme de garbage collection d’objets
distants
• Ce mécanisme utilise un algorithme complexe qui maintient un
liste de toutes les références à des objets distants. Un protocole
entre les références d ’objets permet l’incrémentation et la
décrémentation des références. Ainsi, RMI assure un compteur de
référence pour chaque objet distant, lorsque le compteur arrive à 0,
l’objet est alors détruit.
• La méthode finalize est bien entendue appelée au moment de la
destruction de l ’objet.

Vous aimerez peut-être aussi