LazyInitializationException sur un composant selectManyMenu (JSF / PrimeFaces)

L'objectif de cet article est d'éviter la levée d'une LazyInitializationException lors de l'utilisation d'un composant JSF selectManyMenu (ou PrimeFaces).

L'application, sur laquelle je travaille actuellement, repose sur les technologies JSF et JPA (Hibernate). J'ai dû, pour les besoins du projet, créer une page contenant un composant selectManyMenu, qui permet de sélectionner plusieurs éléments d'une liste :

selectManyMenu

Malheureusement, au moment de soumettre le formulaire pour enregistrer, la terrible LazyInitializationException fit son apparition.

Contrairement, aux LazyInitializationException "classiques", la source du problème n'était pas que ma collection (utilisateur.roles) n'était pas chargée. Elle l'était. D'ailleurs, un FetchType EAGER n'aurait pas résolu le problème.

Le problème se situe dans la classe com.sun.faces.renderkit.html_basic.MenuRenderer de JSF.

Explication

En effet, lors de la soumission du formulaire, le composant a besoin de créer une nouvelle instance de la collection pour y ajouter les valeurs soumises. Pour ce faire, il instancie une collection du même type que celle fournie par mon bean.
Ma collection est déclarée en tant que java.util.List. Cependant, celle-ci a été instanciée par Hibernate, donc au lieu d'avoir une ArrayList, nous avons un PersistentBag. La classe MenuRenderer instancie donc un PersistentBag. Par conséquent, au moment de remplir la collection, la méthode add() essaye d'initialiser le proxy à l'aide de la session Hibernate, sauf qu'il n'y a pas de session. Cela se traduit par l'apparition d'une LazyInitializationException.

Solution

Une solution à ce problème consiste à indiquer explicitement, au composant selectManyMenu, le type de collection souhaité. Pour ce faire, il faut utiliser l'attribut collectionType du composant.
Comme ma collection est une List, j'indique que je veux une ArrayList. Si ma collection avait été un Set, j'aurais indiqué un HashSet (ou une autre implémentation de Set).

On obtient donc :

selectManyMenu2

Sources

Zenida'S Blog et Stackoverflow

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.