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

JSF Java Discussion :

Injection de dépendance et constructeur


Sujet :

JSF Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut Injection de dépendance et constructeur
    Salut à tous,

    J'ai un bean managé A en session. J'ai un bean managé B ayant un attribut du type du bean A :
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <managed-bean>
        <managed-bean-name>monBeanA</managed-bean-name>
        <managed-bean-class>com.test.BeanA</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    <managed-bean>
        <managed-bean-name>monBeanB</managed-bean-name>
        <managed-bean-class>com.test.BeanB</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>beanA</property-name>
            <value>#{monBeanA}</value>
        </managed-property>
    </managed-bean>

    A chaque requête, je dois afficher le résultat d'une requête SQL faite dans le bean B. Cette requête a besoin de plusieurs paramètres dont les valeurs sont contenues dans le bean A.

    J'ai d'abord essayé de récupérer les attributs de mon bean A dans le constructeur de mon bean B :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class BeanB {
        private BeanA beanA;
        private List maListe; //la liste à afficher (celle qui contient les résultats de ma requête SQL
     
        public BeanB() {
            maListe = resultatSQL(beanA.attributA, beanA.attributB);
        }
     
        // le getteur et setteur de beanA et de maListe
     
        private List resultatSQL(param1, param2) {
            // renvoie le résultat de ma requête SQL dans un objet List
        }
    }
    Mais je me fais insulter car l'attribut beanA est null, puisqu'il n'a pas encore été initialisé. Il sera initialisé après l'appel au constructeur de la classe B.

    J'ai contourné le problème en appelant la méthode resultatSQL(), non pas dans le constructeur, mais dans le getteur de l'attribut maListe de la classe BeanB. Mais d'autres problèmes se posent :
    1. C'est moche
    2. Je n'ai pas accès aux attributs de maListe (la taille par exemple) tant que getMaListe() n'est pas appelé (avec #{monBeanB.maListe} dans une JSP)


    Existe-t-il un moyen de forcer l'injection de dépendance avant l'appel du constructeur de la classe BeanB (sans devoir installer un framework type Spring ou Seam ) ? Ou peut-être qu'il s'agit d'un problème de conception ?

    Merci !

  2. #2
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Points : 5 059
    Points
    5 059
    Par défaut
    ton bean B est en scope request, il sera créer à chaque requete, c'est bien ce que tu veux faire??
    sinon je trouve que c'est le comportement normal, un bean A qui référence un bean B, le bean B sera instancié après le A.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    Merci pour ta réponse Sniper37.

    Oui effectivement c'est ce que je veux puisque le bean B doit récupérer les résultats à chaque requête (requête HTTP, pas requête SQL ).

    Moi aussi je trouve que c'est un comportement normal. Mais je trouve ma solution de contournement pas très propre. Je débute avec JSF et je ne connais pas encore les bonnes pratiques. Peut-être que je m'y prends mal...

    Comment faire pour appeler une méthode d'un bean à chaque requête HTTP ?

  4. #4
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Points : 5 059
    Points
    5 059
    Par défaut
    le faire dans l'action de la requete ou dans une actionListener.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    1. Que veux tu dire par "dans l'action de la requete" ?
    2. Quand tu dis "dans une actionListener", tu veux parler de la balise <f:actionListener/> ? Ou une classe qui implémente actionListener ? Ou autre chose ?

  6. #6
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Points : 5 059
    Points
    5 059
    Par défaut
    comment tu fais pour passer d'une page à l'autre??
    ou de lancer la requete en restant sur la même page,

    action ou actionListener est l'attribut utilisé dans les composants de controle : commandButton, ou autre.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    C'est bien ce que je pensais.

    Je pense que tu viens de mettre le doigt sur quelque chose. Pour récupérer les derniers résultats en base, la requête SQL dont je parle doit être appelée lorsque l'utilisateur arrive sur le site. Un peu comme une page d'accueil.

    Dans ces conditions, puis-je utiliser un action ou un actionListener ?

    Merci

  8. #8
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Points : 5 059
    Points
    5 059
    Par défaut
    Citation Envoyé par sheepolata Voir le message
    C'est bien ce que je pensais.

    Je pense que tu viens de mettre le doigt sur quelque chose. Pour récupérer les derniers résultats en base, la requête SQL dont je parle doit être appelée lorsque l'utilisateur arrive sur le site. Un peu comme une page d'accueil.

    Dans ces conditions, puis-je utiliser un action ou un actionListener ?

    Merci
    la question a été traité plusieurs fois sur le forum, tu peux faire l'appel dans le constructeur, l'appel sera fait à chaque création du bean, comme c'est un bean request il sera créer à chaque requete.

    tu peux aussi le faire dans la déclaration de la liste, dans le getter ce n'est pas conseillé, à moins de faire vraiment attention de ne faire qu'une seule fois par requete, le getter est appelé plusieurs fois pour une seule requete JSF.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    Désolé si le problème a déjà été abordé . Je n'utilise peut-être pas les bons mots clé pour les recherches.

    C'est exactement ce que je veux faire : appeler ma requête dans mon constructeur. Comme mon bean est en scope request, le constructeur serait appelé à chaque fois, et je pourrais donc faire l'appel à ma requête SQL.

    Seulement, comme je le soulignais dans le premier post, ma requête SQL a des paramètres dont les valeurs sont contenues dans un autre bean que j'injecte à l'aide du fichier faces-config.xml. Le problème est que le bean n'est injecté qu'après l'appel du constructeur du bean "parent". Donc je ne peux pas appeler ma requête SQL dans le constructeur.

    Comprends-tu mieux mon problème ? As-tu besoin d'autres informations ?



    Une autre solution serait d'utiliser la méthode suivante (en reprenant mon exemple du premier post) :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    beanA = (BeanA) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("monBeanA");
    Mais à quoi bon avoir des <managed-property> si c'est pour faire ce genre de contournement ?

  10. #10
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Points : 5 059
    Points
    5 059
    Par défaut
    ce que tu peux faire, utiliser un bean qui pend bean1 et beanB en parametre plus la liste, puisque dans tu utilise les deux en paramètre.
    Ce qui n'est pas normal, c'est d'utiliser beanB avant beanA, tu peux aussi déplacer la liste dans beanA, dans le constructeur tu initialise la liste pour la première fois, normalement après, les prochaines requêtes HTTP se feront à l'aide d'une action utilisateur dans laquelle tu peux recalculer la liste.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    Citation Envoyé par Sniper37
    ce que tu peux faire, utiliser un bean qui pend bean1 et beanB en parametre plus la liste, puisque dans tu utilise les deux en paramètre.
    Ce n'est pas tout à fait ça. Mon BeanB contient, entre autres, le résultat de la requête SQL (la liste). Mon BeanB a besoin, entre autres, de certains attributs contenus dans mon BeanA.

    Je crois que la solution qui me reste est de fusionner les deux beans. C'est quand même bizarre de devoir en arriver là non ?

  12. #12
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Points : 5 059
    Points
    5 059
    Par défaut
    oui c'est bizarre parce que tu as du mal modéliser tes objets, maintenant tu as les possibilités, faut les adapter à ton cas.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    Merci Sniper37 d'avoir pris le temps de m'aider

    La solution s'appelle @PostConstruct. C'est une annotation compatible à partir de JSF 1.2 permettant d'appeler une méthode après le constructeur.

    Mon code devient alors :
    Code java : 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
    public class BeanB {
        private BeanA beanA;
        private List maListe; //la liste à afficher (celle qui contient les résultats de ma requête SQL
     
        public BeanB() {
        }
     
        @PostConstruct
        public void recupererResultatSql() {
            maListe = resultatSQL(beanA.attributA, beanA.attributB);
        }
     
        // le getteur et setteur de beanA et de maListe
     
        private List resultatSQL(param1, param2) {
            // renvoie le résultat de ma requête SQL dans un objet List
        }
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [EJB3] [JBoss] Injection de dépendance circulaire ?
    Par Claythest dans le forum Java EE
    Réponses: 6
    Dernier message: 04/08/2009, 08h11
  2. [Framework] injection de dépendances par constructeur
    Par skud dans le forum Spring
    Réponses: 6
    Dernier message: 16/05/2008, 14h15
  3. [EJB3] Injection de dépendance et Stateful
    Par newbeewan dans le forum Java EE
    Réponses: 1
    Dernier message: 15/05/2007, 07h33
  4. [Integration] [EasyMock] Injection de dépendance à l'éxécution
    Par frangin2003 dans le forum Spring
    Réponses: 2
    Dernier message: 06/03/2007, 11h06
  5. Spring + TagSupport et injection de dépendance
    Par worldchampion57 dans le forum Spring Web
    Réponses: 2
    Dernier message: 26/02/2007, 09h01

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