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

Java EE Discussion :

Injection de dépendance dans un Bean (MVC)


Sujet :

Java EE

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut Injection de dépendance dans un Bean (MVC)
    Bonjour,
    Dans une application Web, j'arrive à faire de l'injection de dépendance dans une servlet, mais je n'arrive pas à le faire dans un bean et je voudrais bien continuer à respecter l'architecture MVC.
    La servlet est là pour établir le lien entre les pages et les objets métiers, c'est donc me semble-t-il au Beans métiers de référencer les EJB.
    Mais tout se passe comme si les beans n'avaient pas accès au contexte.
    Quelqu'un a-t-il une idée ?
    merci,

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 70
    Par défaut
    Citation Envoyé par clem_alain Voir le message
    Bonjour,
    Dans une application Web, j'arrive à faire de l'injection de dépendance dans une servlet, mais je n'arrive pas à le faire dans un bean et je voudrais bien continuer à respecter l'architecture MVC.
    La servlet est là pour établir le lien entre les pages et les objets métiers, c'est donc me semble-t-il au Beans métiers de référencer les EJB.
    Mais tout se passe comme si les beans n'avaient pas accès au contexte.
    Quelqu'un a-t-il une idée ?
    merci,
    Une chose importante, l’injection « classique » (sans web beans) ne marche que sur des composants managed (dont le cycle de vie est géré par le conteneur).

    Dans quel composant veux tu injecter tes EJB ?
    Comment fais tu cette injection ?
    Peut on voir un exemple de code ?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut
    Bonjour,
    Evidemment l'exemple est simpliste, mais l'objectif est dans un premier temps de maîtriser l'environnement.
    Je viens du monde .NET où j'ai une assez longue expérience et je dois acquérir des compétences dans J2EE, donc je commence simple.
    D'une manière générale d'ailleurs je constate que l'on trouve de tout et n'importe quoi dans cet environnement, y compris du code proposé par les éditeurs qui ne fonctionne pas ou alors qui est incomplet ou bien obsolète.
    J'ai un peu l'impression qu'on se gargarise de mots bien ronflants, mais que derrière il n'y pas grand chose. Par exemple on parle beaucoup de J2EE, EJB, ... et en réalité on fait des servlet/jsp/jstl (ce qui est déjà pas mal).
    Donc si vous pouviez me dépêtrer, ce serait vraiment le bienvenu ;-)

    Voici le contexte :

    L'EJB :
    package pkgCalcul;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import javax.ejb.Remote;
    @Remote
    public interface CalculerRemote {
        public float addition(float nb1, float nb2);
        public float soustraction(float nb1, float nb2);
        public float produit(float nb1, float nb2);
        public float division(float nb1, float nb2);
    }
    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
    package pkgCalcul;
    import javax.ejb.Stateless;
    @Stateless(mappedName="CalculerRemote")
    public class Calculer implements CalculerRemote {
        public Calculer() {
     
        }
        public float addition(float nb1, float nb2){
        	return (nb1 + nb2);
        }
        public float soustraction(float nb1, float nb2){
        	return (nb1 - nb2);
        }
        public float produit(float nb1, float nb2){
        	return (nb1 * nb2);
        }
        public float division(float nb1, float nb2){
        	return (nb1 / nb2);
        }
    }
    Le Bean de l'application Web :
    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
    package metier;
    import pkgCalcul.*;
    public class CalculBean {
        private float _nb1, _nb2, _resultat;
        private int _operation;
        @EJB(mappedName="CalculerRemote")
        private CalculerRemote unCalcul;
        public float getNb1() {
            return _nb1;
        }
        public void setNb1(float nb1) {
            this._nb1 = nb1;
        }
        public float getNb2() {
            return _nb2;
        }
        public void setNb2(float nb2) {
            this._nb2 = nb2;
        }
        public float getResultat() {
            return _resultat;
        }
        public void setResultat(float resultat) {
            this._resultat = resultat;
        }
        public int getOperation() {
            return _operation;
        }
        public void setOperation(int operation) {
            this._operation = operation;
        }
     
        public CalculBean() throws Exception{
        }
     
        public String Calculer() throws Exception{
            int operation = getOperation();
            try{
            switch (operation){
                case 0:
                    setResultat(unCalcul.addition(getNb1(), getNb2()));
                    break;
                case 1:
                    setResultat(unCalcul.soustraction(getNb1(), getNb2()));
                    break;
                case 2:
                    setResultat(unCalcul.produit(getNb1(), getNb2()));
                    break;
                case 3:
                    setResultat(unCalcul.division(getNb1(), getNb2()));
                    break;
            }
            return ("");
            }catch(Exception ex){
                throw ex;
            }
        }
    }
    La servlet :
    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
    public class Calcul extends HttpServlet {
        ...
        private String FaireCalcul(HttpServletRequest request) throws Exception {
            CalculBean rCalcul;
            String pageReponse;
            try {
                pageReponse = "/index.jsp";
                float nb1 = Float.parseFloat(request.getParameter("txtNb1"));
                float nb2 = Float.parseFloat(request.getParameter("txtNb2"));
                int operation = Integer.parseInt(request.getParameter("cbOperation"));
                float resultat = Calculer(operation, nb1, nb2);
                rCalcul = new CalculBean();
                rCalcul.setNb1(nb1);
                rCalcul.setNb2(nb2);
                rCalcul.Calculer();
                request.setAttribute("rCalc", rCalcul);
                return (pageReponse);
            } catch (Exception e) {
                throw new ServletException(e.getMessage());
            }
        }
        ...
    }

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 70
    Par défaut
    Evidemment l'exemple est simpliste, mais l'objectif est dans un premier temps de maîtriser l'environnement.
    Je viens du monde .NET où j'ai une assez longue expérience et je dois acquérir des compétences dans J2EE, donc je commence simple.
    Bienvenu dans le monde J2EE, le monde de l'Open.

    D'une manière générale d'ailleurs je constate que l'on trouve de tout et n'importe quoi dans cet environnement, y compris du code proposé par les éditeurs qui ne fonctionne pas ou alors qui est incomplet ou bien obsolète.
    La communauté est bien active dans ce monde mais il faut faire très attention aux sources . Il faut dire aussi qu'une chose est de trouver du code et une autre est de le faire fonctionner (dans un environnement adéquat).

    J'ai un peu l'impression qu'on se gargarise de mots bien ronflants, mais que derrière il n'y pas grand chose. Par exemple on parle beaucoup de J2EE, EJB, ... et en réalité on fait des servlet/jsp/jstl (ce qui est déjà pas mal).
    En réalité, les premiers pas dans ce monde ne sont jamais faciles. Mais avec un peu de recherches et de persévérances on fini par attendre le but.
    Il faut chercher des repères, comprendre des expressions bizarres (ce que tu appelles les "mots bien ronflants" ). En général, ces expressions sont loin d être de « gros mots pour ne rien dire », ce sont très souvent des mots utilisés dans les différents JSR. Donc vouloir apprendre J2EE c'est accepter ces mots (Servlet, JSP, EJB, JPA, JPQL, etc...).

    Donc si vous pouviez me dépêtrer, ce serait vraiment le bienvenu ;-)
    En J2EE (sans webBeans et sans spring), tu ne peux utiliser l'injection que dans des classes gérées par un conteneur (Servlet, EJB, Managed Beans JSF, etc...). On ne peut pas faire de l’injection dans une classe simple . Ca veux dire que tu ne peux pas faire d'injection dans ta classe CalculBean.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut
    Bonjour,
    Effectivement j'ai trouvé la même indication ailleurs.
    Un correspondant m'a précisé que cela avait changé avec J2EE6 et où l'on pouvait opter pour l'option CDI dans le descripteur de déploiement et que cela transformait tous les composants (au sens large du terme) en composants gérés ("managés") par le serveur d'applications.
    J'ai testé, mais cela n'a pas eu l'effet escompté. Soit je m'y suis mal pris, soit c'était erroné.
    J'ai tenté une expérience avec JSF (1.2) et là cela a fonctionné parfaitement. Cet environnement ressemble étrangement à ASP.NET d'ailleurs.
    Bizarrement il ne semble pas très utilisé, sauriez-vous pourquoi et par voie de conséquence, faut-il investir dessus ou pas ?

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par clem_alain Voir le message
    Effectivement j'ai trouvé la même indication ailleurs.
    Un correspondant m'a précisé que cela avait changé avec J2EE6 et où l'on pouvait opter pour l'option CDI dans le descripteur de déploiement et que cela transformait tous les composants (au sens large du terme) en composants gérés ("managés") par le serveur d'applications.
    Oui, c'est bien ça, les choses ont changé avec Java EE6 (au passage, on ne dit pas/plus J2EE6); il suffit d'activer CDI (Contexts and Dependency Injection for Java EE6). C'est ce que salber a appelé WebBeans (en fait c'était son nom durant le développement de la JSR, ils l'ont renommé juste avant la sortie de EE6 parce que 'WebBeans' ne reflétait pas toute son offre...)

    Citation Envoyé par clem_alain Voir le message
    J'ai testé, mais cela n'a pas eu l'effet escompté. Soit je m'y suis mal pris, soit c'était erroné.
    Normalement, il te suffit d'ajouter un fichier nommé beans.xml (fichier qui peut être totalement vide) dans le WEB-INF de ton application web, et tout est OK pour faire tes injections d'EJB dans un POJO simple.

    Citation Envoyé par clem_alain Voir le message
    J'ai tenté une expérience avec JSF (1.2) et là cela a fonctionné parfaitement. Cet environnement ressemble étrangement à ASP.NET d'ailleurs.
    Bizarrement il ne semble pas très utilisé, sauriez-vous pourquoi et par voie de conséquence, faut-il investir dessus ou pas ?
    Avec JSF ça a fonctionné parce que les beans sont gérés par un container qui donc se charge de faire l'injection, comme le dit salber à propos des managed beans.

    JSF est le framework web Java le plus utilisé, juste un peu avant ou après Struts 1.x/2.x, mais ce n'est pas celui qui a la meilleure "presse". En tout cas, jusqu'à la version 1.2 incluse, JSF avait de sérieuses lacunes que beaucoup de développeurs n'arrêtaient pas de dénoncer, certains allant même jusqu'à prédire la mort du framework. Mais rien y a fait, JSF était toujours très utilisé par la majorité silencieuse, surtout qu'il y avait beaucoup de workarounds apportés par les différentes librairies de composants jsf (RichFaces, PrimeFaces, Tomahawk...) et surtout par des frameworks comme Seam.

    La plupart des problèmes ont été résolus dans JSF 2.0, ce que tu devrais utiliser puisque tu fais ton apprentissage avec Java EE 6. JSF est devenu beaucoup plus simple à utiliser: plus facile maintenant de créer ses propres composants composites; utilise Facelets par défaut, qui est certainement le meilleur outil de templating actuellement; s'intègre naturellement avec les autres technologies EE6 (Bean Validation, CDI,...).
    Bref, il faut l'essayer.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut
    Bonjour,
    Merci pour cette réponse très complète, je vais tester CDI en ajoutant ce beans.xml qui effectivement n'y était pas.
    D'autre part je vais réellement investir sur JSF 2.0, ce que vous m'en dites confirme l'impression qu'une première approche rapide m'avait laissée.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut
    Bonjour,
    J'ai reconstruit sous NetBeans 69.1/GlassFish 3.1 et EE6, une application complète qui reprend le code ci-dessus avec Stateful à la place de Stateless, le fichier de configuration beans.xml est bien présent cette fois, tout se déploie correctement (enfin sans message d'erreur), mais l'injection de dépendance ne fonctionne toujours pas : exception de type NullPointer lors de l'appel suivant : setResultat(unCalcul.addition(getNb1(), getNb2()));
    Si je remplace l'injection de dépendance par un appel JNDI :
    public CumulBean() throws Exception {
    Context ctx = new InitialContext();
    unCumul = (CumulerRemote)ctx.lookup("CumulerRemote");

    }
    Note : un fichier de properties est placé dans le package.

    Tout fonctionne correctement, ce n'est donc pas un problème côté EJB.
    Si quelqu'un pouvait faire la manip et me dire ce qu'il obtient cela me ferait faire un grand pas en avant, je tourne en rond depuis un moment et j'aime bien comprendre pourquoi cela marche et aussi pourquoi cela ne marche pas.
    Merci d'avance,

  9. #9
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Bonjour,

    Bon, je n'ai pas testé moi-même, mais je peux voir à partir de ton code d'où vient le problème. A vrai dire, je ne suis pas très certain que le code fonctionne quand l'ejb est stateless (c'est vraiment le cas?).

    Le problème c'est que dans ta servlet, tu instancies directement ton bean (rCalcul = new CalculBean()), dès lors le container n'a aucune prise sur cette instanciation et ne peut donc pas faire l'injection pour toi avant tout appel de méthode. D'où le NullPointerException. C'est pour ça que la seule façon qui te reste dans ce cas pour avoir une instance de l'ejb c'est de passer par un lookup JNDI.

    Pour que l'injection fonctionne de bout en bout, il te faudrait aussi injecter le bean CalculBean dans la servlet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @Inject private CalculBean rCalcul;
    Mais à partir de là, il va falloir commencer à faire attention au scope de ton bean, qui par défaut est @Dependent. Etant donné qu'il n'y a qu'une seule instance de la servlet durant toute la durée de l'application, l'instance de ton ejb stateful injectée par cdi risquerait de durer jusqu'à la fermeture de l'application. Ce qui en général n'est pas ce qu'on veut.
    Il faudrait donc définir un scope pour le bean (@RequestScoped par exemple):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    package metier;
     
    import javax.enterprise.context.RequestScoped;
    import pkgCalcul.*;
     
    @RequestScoped
    public class CalculBean {
        private float _nb1, _nb2, _resultat;
        private int _operation;
        @EJB(mappedName="CalculerRemote")
        private CalculerRemote unCalcul;
    ...
    }
    Bon, il y a encore quelques trucs à redire sur ton code, comme par exemple le fait que tu n'aies peut-être pas besoin d'interface remote pour ton ejb, une interface locale étant suffisante et moins coûteuse en termes de performance, etc.

    Mais je pense que les quelques changements suggérés ci-dessus devraient suffir pour t'aider à y voir plus clair par rapport à ce que fait le container.

Discussions similaires

  1. Réponses: 0
    Dernier message: 24/05/2013, 02h02
  2. Réponses: 4
    Dernier message: 25/05/2011, 09h23
  3. Weblogic 10.0 : injection d'EJB dans managed bean JSF
    Par loic38_01 dans le forum Weblogic
    Réponses: 1
    Dernier message: 05/09/2008, 13h46
  4. [EJB3] Injection de dépendances lorsque le jar se trouve dans un ear
    Par Invité(e) dans le forum Java EE
    Réponses: 14
    Dernier message: 18/06/2008, 11h54
  5. [EJB3] Injection dans un bean
    Par *alexandre* dans le forum Java EE
    Réponses: 5
    Dernier message: 14/02/2007, 09h17

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