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 !:P
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) ???.