Evénements
Java Beans
Java RMI
X. BLANC & J. DANIEL
[Link]@[Link] , [Link]@[Link]
Les événements dans Java
X. BLANC & J. DANIEL
[Link]@[Link] , [Link]@[Link]
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
[Link]
Cet événement est lancé lorsque l’on clique sur un bouton.
• Les classes capables de recevoir cet événement doivent implanter
l’interface
[Link]
• 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 [Link] {
public void actionPerformed(ActionEvent e) {
[Link](“evenement recu !”);
}
}
…
// quelque part dans le programme, le lien entre le receveur et le lanceur
[Link] button = new [Link](“click”);
…
[Link](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
[Link]
• 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
[Link]
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 [Link] 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 [Link]
– Créer l’interface Listener qui hérite de [Link]
– 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
[Link]@[Link] , [Link]@[Link]
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 [Link]
• 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 [Link].*;
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
public void addPropertyChangeListener( PropertyChangeListener l) {
[Link](l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
[Link](l);
}
public void setLabel(String newLabel) {
String oldLabel = label;
label = newLabel;
sizeToFit();
[Link]("label", oldLabel, newLabel);
}
Propriétés Liées
• Le Beans contenant la propriété dépendante
public class MyClass implements [Link],
[Link] { …
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 [Link].*;
private VetoableChangeSupport vetos = new VetoableChangeSupport(this);
public void addVetoableChangeListener(VetoableChangeListener l) {
[Link](l)}
public void removeVetoableChangeListener(VetoableChangeListener l){
[Link](l);}
public void setPriceInCents(int newPriceInCents) throws PropertyVetoException {
int oldPriceInCents = ourPriceInCents;
[Link]("priceInCents",new Integer(oldPriceInCents),
new Integer(newPriceInCents));
ourPriceInCents = newPriceInCents;
[Link]("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 [Link] 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 = [Link]([Link]());
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 [Link] qui
décrit le contenu de l’archive.
• Pour les Java Beans le manifest doit contenir:
Name: [Link]
Java-Bean: True
Le fichier Jar
• Pour archiver des classes dans un fichier Jar:
jar cfm [Link] [Link] liste_fichier
ex:jar cfm [Link] [Link] *.class
Java RMI
X. BLANC & J. DANIEL
[Link]@[Link] , [Link]@[Link]
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 [Link]
• 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 [Link].*;
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 [Link].*;
import [Link].*;
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 {
[Link](new RMISecurityManager());
CalculatriceImpl calc = new CalculatriceImpl();
String nom = "Calculatrice";
[Link]([Link]);
}
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 [Link].*;
public class CalculatriceClient {
public static void main(String args[]) {
String serverName = "Calculatrice";
CalculatriceInterface calc;
try {
calc = (CalculatriceInterface)
[Link]([Link]());
[Link](" 6+2= "+[Link](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 [Link]).
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.