IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[MVC][Swing][EJB] - Est ce que je pars dans la bonne direction ?


Sujet :

AWT/Swing Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 71
    Points : 49
    Points
    49
    Par défaut [MVC][Swing][EJB] - Est ce que je pars dans la bonne direction ?
    Hello everybody !
    Voilà, je suis en train de réaliser une appli qui mélange des ejb et du swing.
    Pour la partie EJB, je n'ai pas trop de soucis, par contre, l'IHM de ces ejb, c'est un peu plus complexe

    J'ai lu pratiquement tous les tutos concernant MVC appliqué à swing, et j'avouerai que chacun fais un peu comme il veut. Certains mélange, à mon sens, le controler et la view...
    Donc j'ai essayé de récupérer ce que j'ai vu ici et là, et voilà ce que j'ai pondu:

    Mon entity:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public class Moniteur extends Individu implements Serializable {
        [....]
    }
    public class Individu implements Serializable {
     
    	private Integer idIndividu;
    	private String nom;
    	private String prenom;
    	private Date dateNaissance;
    	private Adresse adresse;
        [....]
    }
    Mon model:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    public class MoniteurModel {
     
        private AdresseModel adresseModel;
        private EventListenerList listeners;
        private Moniteur moniteur;
        private String nom, prenom;
     
     
        public MoniteurModel(){
            listeners = new EventListenerList();
            moniteur = new Moniteur();
            adresseModel = new AdresseModel();
        }
     
        public void addMoniteurListener(MoniteurListener moniteurListener){
            listeners.add(MoniteurListener.class, moniteurListener);
        }
        public void removeMoniteurListener(MoniteurListener moniteurListener){
            listeners.remove(MoniteurListener.class, moniteurListener);
        }
        private MoniteurListener[] getMoniteurListeners(){
            return listeners.getListeners(MoniteurListener.class);
        }
        public void notifyMoniteurListener(String propriete, Object oldValue, Object newValue){
            for (MoniteurListener m : getMoniteurListeners()) {
                m.moniteurProprieteChanged(propriete, oldValue, newValue);
            }
        }
     
        public Moniteur getMoniteur(){
            return moniteur;
        }
     
        public void setMoniteur(Moniteur m){
            moniteur = m;
            setNom(moniteur.getNom());
            setPrenom(moniteur.getPrenom());
            getAdresseModel().setAdresse(m.getAdresse());
        }
     
        public String getNom(){
            return moniteur.getNom();
        }
        public void setNom(String nom){
            Object oldValue = this.nom;
            Object newValue = nom;
            moniteur.setNom(nom);
            notifyMoniteurListener("nom", oldValue, newValue);
        }
     
        public void setPrenom(String prenom){
            Object oldValue = this.prenom;
            Object newValue = prenom;
            moniteur.setPrenom(prenom);
            notifyMoniteurListener("prenom", oldValue, newValue);
        }
        public String getPrenom(){
            return moniteur.getPrenom();
        }
     
        public AdresseModel getAdresseModel() {
            return adresseModel;
        }
     
        public void setAdresseModel(AdresseModel adresseModel) {
            this.adresseModel = adresseModel;
        }
    }
    Une partie de ma view:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class JMoniteurPanel extends javax.swing.JPanel implements MoniteurListener{
     
        /** Creates new form JMoniteurPanel */
        public JMoniteurPanel() {
            initComponents();
        }
     
        public void moniteurProprieteChanged(String propriete, Object oldValue, Object newValue) {
            if(propriete.equals("prenom"))
                jtPrenom.setText(newValue.toString());
            else if(propriete.equals("nom"))
                jtNom.setText(newValue.toString());
        }
     
        [....]
     
        // Variables declaration - do not modify                     
        private javax.swing.JLabel jLabel1;
        private javax.swing.JLabel jLabel2;
        private javax.swing.JTextField jtNom;
        private javax.swing.JTextField jtPrenom;
        // End of variables declaration                   
     
    }
    L'autre partie de la vue:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public class JFrameMoniteur extends javax.swing.JFrame {
     
        /** Creates new form JFrameMoniteur */
        public JFrameMoniteur() {
            initComponents();
        }
     
        public JButton getCreateButton(){
            return jbCreate;
        }
     
        public JMoniteurPanel getPanelMoniteur(){
            return jMoniteurPanel1;
        }
        public JAdressePanel getPanelAdresse(){
            return jAdressePanel1;
        }
     
       [.....]
     
        // Variables declaration - do not modify                     
        private view.JAdressePanel jAdressePanel1;
        private view.JMoniteurPanel jMoniteurPanel1;
        private javax.swing.JButton jbCreate;
        // End of variables declaration                   
     
    }
    Mon controler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class MoniteurControler implements ActionListener{
     
        public MoniteurModel model;
        public JFrameMoniteur view;
     
        public MoniteurControler(Moniteur m){
            model = new MoniteurModel();
            view = new JFrameMoniteur();
     
            view.getCreateButton().addActionListener(this);
            model.addMoniteurListener(view.getPanelMoniteur());
            model.getAdresseModel().addAdresseListener(view.getPanelAdresse());
     
            model.setMoniteur(m);
        }
     
        public void displayView(){
            view.setVisible(true);
        }   
     
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("Create")){
                System.out.println("Création..."+model.getAdresseModel().getRue());
            }
            else{
                System.out.println("Action inconnu :/");
            } 
     
        }
     
    }
    Et enfin, le lancement de l'appli:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        public static void main(String[] args) {
            Moniteur m = new Moniteur();
            m.setPrenom("Paul");
            m.setNom("DUPONT");
            Adresse a = new Adresse();
            a.setNumeroRue("6");a.setRue("Rue de la source");
            m.setAdresse(a);
            MoniteurControler mc = new MoniteurControler(m);
            mc.displayView();
        }
    Est ce que donc ma façon de procéder est la bonne ? Je vous demande, car ce n'est pas un tuto qui va me le dire....
    Je gère les actions de la vue, dans le controler.
    Le model prévient la vue lorsqu'il y a modification de celui ci...

    Le soucis que je n'arrive pas à résoudre, c'est le lancement de la fenêtre (view = new JFrameMoniteur(); ) que je ne fais pas en utilisant SwingUtilities... est ce grave docteur ?
    Vous avez une meilleur solution ?

    Bien cordialement !

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Salut !

    Dans le concept, c'est bon. Juste deux ou trois remarques mineures : est-il nécessaire de faire redondance en définissant un MoniteurModel ? Un EJB est capable d'avoir des méthodes qui lui sont propres d'un côté (la gestion des événements, par exemple) sans en transmettre les variables (grâce au mot-clé transient). Le wrapper MoniteurModel est donc assez redondant.

    Par contre, la gestion de tes boutons semble un peu limitée. Essaie d'utiliser les actions au maximum. Elles te faciliteront toujours la tâche. Cela produit en général un contrôleur par action possible, plutôt qu'un contrôleur global ou par domain objet, mais ta gestion en sera assez facilitée, malgré la multitude d'objets à réaliser.

    La dernière remarque concerne, comme tu dois t'en douter, l'absence de distinction entre l'EDT et d'autres threads. La gravité de ceci peut être importante si ton EJB a des problèmes de communication avec le serveur d'application, si un traitement avant l'envoi des données vers le serveur est plutôt long, ... L'affichage de ton application risque alors de se figer. Il est donc bien recommandé d'utiliser à bon escient les différents Threads à ta disposition. Pour t'aider, il existe quelques outils comme la JSR 296 ou l'objet SwingWorker (intégré en standard dans java depuis la version 6).

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 71
    Points : 49
    Points
    49
    Par défaut
    Citation Envoyé par dingoth Voir le message
    Salut !

    Dans le concept, c'est bon. Juste deux ou trois remarques mineures : est-il nécessaire de faire redondance en définissant un MoniteurModel ? Un EJB est capable d'avoir des méthodes qui lui sont propres d'un côté (la gestion des événements, par exemple) sans en transmettre les variables (grâce au mot-clé transient). Le wrapper MoniteurModel est donc assez redondant.
    Alors justement... je me la suis posé cette question...
    Donc si j'ai bien compris, il n'est pas gênant d'inclure la gestion des évènements (par exemple) directement dans l'EJB entity ?! Ca ne risque pas de "polluer" le code ?
    Si je suis amené à les utiliser avec JSF, pas de soucis de clareté non plus ?


    Citation Envoyé par dingoth Voir le message
    Par contre, la gestion de tes boutons semble un peu limitée. Essaie d'utiliser les actions au maximum. Elles te faciliteront toujours la tâche. Cela produit en général un contrôleur par action possible, plutôt qu'un contrôleur global ou par domain objet, mais ta gestion en sera assez facilitée, malgré la multitude d'objets à réaliser.
    Oui, ça risque de faire pas mal de classe ^^
    Donc tu me conseilles une classe par action des boutons...hmm ok !
    Et je pensais aussi créer un seul controler qui s'occuperait de voir si des champs (field, combo, check...) ont changé, auquel cas prévenir le model...

    Citation Envoyé par dingoth Voir le message
    La dernière remarque concerne, comme tu dois t'en douter, l'absence de distinction entre l'EDT et d'autres threads. La gravité de ceci peut être importante si ton EJB a des problèmes de communication avec le serveur d'application, si un traitement avant l'envoi des données vers le serveur est plutôt long, ... L'affichage de ton application risque alors de se figer. Il est donc bien recommandé d'utiliser à bon escient les différents Threads à ta disposition. Pour t'aider, il existe quelques outils comme la JSR 296 ou l'objet SwingWorker (intégré en standard dans java depuis la version 6).
    Merci pour cette référence, je vais prendre le temps de regarder ce SwingWorker !

    Merci en tout cas de m'avoir éclairer un peu sur le sujet

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Pour info, une action peut tout simplement appeler une méthode d'une autre classe si tu veux Ca te permet d'avoir des mini-contrôleurs présents juste pour activer le contrôleur principal

    Pour la première question, bah non, ça ne pollue pas le code ! Si tu as besoin d'une gestion d'événements mieux vaut l'intégrer directement dans le Bean plutôt que de faire un Wrapper. Sauf si tu as une architecture appropriée bien sûr (genre un truc bien complexe avec plein plein d'interfaces )

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 71
    Points : 49
    Points
    49
    Par défaut
    Hello

    Bon c'est le drame... J'ai donc inclus dans mon entity bean l'EventListernerList
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @Table(name = "individus")
    public class Individu implements Serializable {
     
    [.....] 
     
        @Transient
        private EventListenerList listeners;
     
        @Transient
        public void addListener(Listener listener) {
            listeners.add(Listener.class, listener);
        }
     
        @Transient
        public void removeListener(Listener listener) {
            listeners.remove(Listener.class, listener);
        }
     
        private Listener[] getListeners() {
            return listeners.getListeners(Listener.class);
        }
     
        @Transient
        public void notifyListener(String propriete, Object oldValue, Object newValue) {
            for (Listener l : getListeners()) {
                l.propertieChanged(Individu.class, propriete, oldValue, newValue);
            }
        }
    }
    je me suis fait une interface "générique" Listener:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public interface Listener extends EventListener{
        public void propertieChanged(Class clazz, String propriete, Object oldValue, Object newValue);
    }
    Et puis bah j'ai mon JPanel qui implemente cette interface, et je fais sur mon individu un addListener(Panel);
    Sauf qu'au moment de persister mon bean, et bah j'ai une belle exception:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ATTENTION: "IOP00100006: (BAD_PARAM) Class javax.swing.GroupLayout is not Serializable"
    Ce qui n'est pas étonnant, puisque qu'il n'arrive pas à sérializer tout le panel...
    Donc qu'est ce que vous me conseiller ?
    De faire un remove de tout les panels juste avant de persister ?
    Ou finalement de wrapper mes beans ?
    Ou bien une solution magique ?

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Si tu as cette erreur, c'est que tu as trop sérialisé. Même si c'est possible, il vaut mieux ne pas sérialiser les objets graphiques pour reconstruire l'interface à partir du modèle. Or, tes listeners sont en partie des objets swing apparamment, ce qui pose ce problème de layout non sérialisé (ce qui est un bug d'ailleurs : tout composant de javax.swing doit être sérialisable).

    Quand j'ai parlé d'utiliser le mot-clé transient, je parlais bien du mot-clé transient de Java, pas de l'annotation de la persistance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    @Mes @Annotations
    public class Individu implements Serializable {
        [...] 
        private transient EventListenerList listeners;
        [...]
    }
    D'ailleurs, regarde, il est reconnu par le code de DVP : il est en bleu

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 71
    Points : 49
    Points
    49
    Par défaut
    Citation Envoyé par dingoth Voir le message
    Si tu as cette erreur, c'est que tu as trop sérialisé. Même si c'est possible, il vaut mieux ne pas sérialiser les objets graphiques pour reconstruire l'interface à partir du modèle. Or, tes listeners sont en partie des objets swing apparamment, ce qui pose ce problème de layout non sérialisé (ce qui est un bug d'ailleurs : tout composant de javax.swing doit être sérialisable).

    Quand j'ai parlé d'utiliser le mot-clé transient, je parlais bien du mot-clé transient de Java, pas de l'annotation de la persistance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    @Mes @Annotations
    public class Individu implements Serializable {
        [...] 
        private transient EventListenerList listeners;
        [...]
    }
    Ah ok
    Je vais tester ça ! Et regarder à quoi correspond exactement ce mot clé en même temps ^^
    Citation Envoyé par dingoth Voir le message
    D'ailleurs, regarde, il est reconnu par le code de DVP : il est en bleu

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 71
    Points : 49
    Points
    49
    Par défaut

    Une fois mon bean persisté, du fait que EvenListenerList soit transcient, l'objet listeners est null
    Normal, c'est le but de transcient...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Individu i = new Individu();
    i.setNom("Michelin");
    i.setPrenom("Renault");
    i = DelegateAutoEcoleBean.createMoniteurs(i);
     
    // Une belle exception est levé, car i ne peut pas notifier les listeners, puisque la persistence a vidé les listeners
    i.setDateNaissance(new Date());


    Tu n'aurais pas un tutorial qui explique comment utiliser les beans directement comme model ?
    Sinon, je vais devoir wrapper le bean, mais ça ne me plait pas pour autant :s

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Il faut bien entendu instancier tous les éléments non-sérialisés (transient, donc) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    @Mes @Annotations
    public class Individu implements Serializable {
        [...] 
        private transient EventListenerList listeners = new EventListenerList();
        [...]
    }
    Par contre, effectivement, les listeners sont donc remis à une liste vide. Mais c'est normal dans un modèle MVC : tu dois seulement ajouter des listeners aux modèles que tu affiches, pas aux autres. C'est à ton contrôleur de gérer cela. (Le contrôleur doit également supprimer les écouteurs une fois que l'objet ne doit plus être affiché )

Discussions similaires

  1. Qu'est-ce que le event dans "if(CLK event and CLK=1)then"
    Par crispix.prog dans le forum VHDL
    Réponses: 1
    Dernier message: 14/01/2013, 21h50
  2. [AC-2007] Création d'un BdD, est ce que je suis dans la bonne voie
    Par Hitman_11 dans le forum Modélisation
    Réponses: 2
    Dernier message: 01/11/2009, 17h38
  3. Réponses: 18
    Dernier message: 28/02/2008, 10h27
  4. Réponses: 4
    Dernier message: 12/03/2005, 16h43
  5. [XML/XSL] Est ce que je pars sur une bonne base ?
    Par dinbougre dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 03/12/2004, 23h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo