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 :

Problème utilisation relationship entre 2 Beans CMP, par client EJB [EJB2.1]


Sujet :

Java EE

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 14
    Points : 17
    Points
    17
    Par défaut Problème utilisation relationship entre 2 Beans CMP, par client EJB
    Un problème bizarre :

    J'ai JBoss comme serveur d'applications.

    J'ai 2 EntityBean CMP, Commande et LigneCommande, liés par une relation 1=>n
    (1 commande est liée à plusieurs lignes de commandes)
    La relation one to many (ligneCommandes) est définie dans le fichier ejb-jar.xml (section relationship)

    J'ai une interface distante pour Commande, et une interface locale pour LigneCommande.

    Des méthodes Collection getLigneCommandes et setLigneCommandes (Collection) sont définies au niveau de Commande (abstract pour le bean et standard pour l'interface distante).

    J'ai enfin un client EJB qui appelle l'EJB distant Commande;

    La méthode setLigneCommandes fonctionne bien (à l'intérieur du bean Commande et appelée du client EJB).
    La méthode getLigneCommandes() fonctionne bien à l'intérieur du bean Commande.
    (par exemple, des LigneCommande peuvent être crées avec l'interface locale, et ajoutée à la collection getLigneCommandes (), à chaque ajout, le lien relationnel est bien mis à jour, montrant que le mapping objet/relationnel 1=>n fonctionne correctement),
    Par contre, cela ne fonctionne pas lorsque la méthode getLigneCommandes() est appelée par le client EJB (cela provoque une Exception java.lang.reflect.UndeclaredThrowableException
    lorsque l'on essaie de récupérer la collection des LigneCommande)

    J'ai pensé un moment à un problème local/distant, mais pourquoi cela marche-t-il, appelé du client EJB, avec le set (Collection) et pas avec le Collection get() !!

    Bon, il y a bien une astuce - qui fonctionne - consistant (dans Commande) à copier la collection getLigneCommandes dans un ArrayList, et de retourner cet ArrayList - cela oblige à déclarer une autre méthode (pour Commande) style getCopyListeCommandes, mais c'est très lourd.

    Si vous avez une idée, ou mieux si vous pouvez me donner un petit exemple de code - correspondant à mon problème - qui fonctionne, cà serait très très sympa !

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Bonjour,
    C'est un problème lié aux interfaces locales/distantes. Le bean LigneCommande n'ayant que des interfaces locales, tu ne peux pas l'appeler depuis un client distant, et les beans qui y ont accès (en l'occurence le bean Commande) ne devraient pas en renvoyer une instance à travers leur interface distante. Or la collection renvoyée par la mathode "getLigneCommandes()" est composée d'interfaces locales de LigneCommande qui ne sont accessibles qu'à des clients locaux. Par contre, quand tu dis que la méthode "setLigneCommandes(Collection)" marche bien depuis le client distant, je ne suis pas certain d'avoir bien compris. Comment obtiens-tu les références de LigneCommande que tu utilises pour remplir la collection avant de la passer à la méthode "set(Collection)" si le client distant n'a pas de vue sur le bean LigneCommande ?
    Autre chose, normalement la spec ne permet pas d'ajouter les méthodes CMR (Container-Managed Relationships) sur l'interface Remote, tu devrais éviter de le faire.
    Cela dit, une meilleure solution serait que tu explores le pattern Value Object (ou Data Transfer Object), il résout ce genre de problématique, et surtout ça permettrait d'adopter les bonnes habitudes de conception. ça ne devrait pas être très difficile de trouver quelque docs là-dessus, mais si tu as besoin d'aide n'hésite pas.
    SCJP 5 / SCBCD 1.3 Certified

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 14
    Points : 17
    Points
    17
    Par défaut Précisions (lignes de couleur)
    [C'est un problème lié aux interfaces locales/distantes. Le bean igneCommande n'ayant que des interfaces locales, tu ne peux pas l'appeler depuis un client distant, et les beans qui y ont accès (en l'occurence le bean Commande) ne devraient pas en renvoyer une instance à travers leur interface distante. Or la collection renvoyée par la mathode "getLigneCommandes()" est composée d'interfaces locales de LigneCommande qui ne sont accessibles qu'à des clients locaux.
    Par contre, quand tu dis que la méthode "setLigneCommandes(Collection)" marche bien depuis le client distant, je ne suis pas certain d'avoir bien compris. Comment obtiens-tu les références de LigneCommande que tu utilises pour remplir la collection avant de la passer à la méthode "set(Collection)" si le client distant n'a pas de vue sur le bean LigneCommande ?]
    Avec mon "astuce", j'ai réussi à rapatrier des instances locales =>c'est un peu torturé, grâce à une copie dans un ArrayList (astuce décrite précedemment), j'ai récupéré les instances locales de LigneCommande dans le client EJB, puis je les ai réinjecté dans le setLigneCommandes => cela fonctionne...


    [Autre chose, normalement la spec ne permet pas d'ajouter les méthodes CMR (Container-Managed Relationships) sur l'interface Remote, tu devrais éviter de le faire.]
    Il y a peut-être une piste là, je vais regarder..



    [Cela dit, une meilleure solution serait que tu explores le pattern Value Object (ou Data Transfer Object), il résout ce genre de problématique, et surtout ça permettrait d'adopter les bonnes habitudes de conception. ça ne devrait pas être très difficile de trouver quelque docs là-dessus, mais si tu as besoin d'aide n'hésite pas.]
    Je connais le pattern ValueObject, entre autres...,
    mais vu du client EJB, cela justement tue la notion d'objet (pour LigneCommande), alors qu'elle existe pour Commande...



    En regardant sur le WEB, il semble que ce pourrait être un problème de sérialisation, une Collection n'est peut-être pas implémentée par JBoss par une classe Serializable, alors qu'un ArraYList est serializable, ce qui pourrait peut-être expliquer pourquoi cela marche lorsque l'on copie dans un ArrayList (avant de rapatrier vers le client) ???.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 14
    Points : 17
    Points
    17
    Par défaut Problème de conception
    En y réflechissant, sur le fond, il est vrai qu'il ne faut pas mélanger objets distants et locaux...

    Après contrôle, même si avec un ArrayList, on récupère bien une liste d'objets (dans le client EJb), il est impossible d'obtenir des propriétés à partir de ces objets, ce sont des proxys non valides, puisqu'il n'y a pas d'interface distante pour LigneCommande.
    Lorsque l'on fait un setLigneCommandes, ces proxys redeviennent valides dans le bean Commande...

    Est-ce que tout cela explique pas pourquoi le Collection get() plante =>
    peut-être...

    Il y a derrière tout cela un problème de conception.
    En fait, si nous prenons un exemple concret, avec un framework comme Struts, on veut pouvoir afficher, une commande avec des lignes de commandes. En general, on met ces informations dans des beans (de scope session HTTP par exemple).
    Le problème est de lier ces beans avec les EJB
    (on n'a pas ce problème avec HIbernate...)
    Si je passe par une Facade et un ValueObject, je dois lire/écrire tous mes beans "Struts" à la main.
    Quel est l'architecture conseillée ?

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Jusque maintenant, l'architecture conseillée que j'ai trouvée c'est celle de SessionFacade /ValueObject pour le transfert des données de beans entité. Hibernate te permet d'y échaper parce qu'il traite déjà les entités sous forme de JavaBean simple, donc des ValueObject en quelque sorte. Sinon il faudrait peut-être voir avec les EJB3 dont la courche persistence est à l'image de celle de Hibernate.
    SCJP 5 / SCBCD 1.3 Certified

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

Discussions similaires

  1. Problème accès aux propriétés entre deux classes liées par many-to-one
    Par moha1984 dans le forum Persistance des données
    Réponses: 1
    Dernier message: 21/06/2010, 10h07
  2. Réponses: 2
    Dernier message: 10/10/2006, 18h59
  3. problème de deploiement d'un Entity Bean CMP
    Par med56 dans le forum JOnAS
    Réponses: 1
    Dernier message: 19/09/2006, 12h32
  4. utilisation d'un managed bean par un autre
    Par Romain93 dans le forum JSF
    Réponses: 6
    Dernier message: 28/07/2006, 10h29
  5. [EJBQL] [CMP] Relation entre deux beans
    Par salome dans le forum Java EE
    Réponses: 1
    Dernier message: 11/07/2005, 23h50

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