Lazy initialization Exception when lazy loading from rendered attribute
antoine.antoine.abside.com Jun 4, 2008 3:52 PMHello,
I've got a strange pb on Seam 2.02SP1.
I've got a first component browseHdl
which initialize a list of item as a datamodel (items) from url parameters.
@Stateful @Name("browseHdl") public class BrowseHandlerBean implements BrowseHandler { @In private EntityManager entityManager; @In(create = true) private SessionHandler sessionHdl; @In(create = true) OrderHome orderHome; @In ApplicationConfig applicationConfig; @Logger private Log log; @DataModel private List<Item> items; @DataModelSelection private Item item; @Factory("items") @SuppressWarnings("unchecked") public void findItems() { log.debug("Launching Request !"); log.debug("group : {0} family : {1}", sessionHdl.getSelGroup(), sessionHdl.getSelFamily()); items = entityManager.createNamedQuery("browseProducts").setParameter( "collectionRef", applicationConfig.getCollection()) .setParameter("groupRef", sessionHdl.getSelGroup()) .setParameter("familyRef", sessionHdl.getSelFamily()) .getResultList(); log.debug("Request returned {0} items", items.size()); } }
This List is used in facelets page to list the items in a rich faces datagrid.
To display information on each item in this page, I use another component (itemHdl) to be able to retrieve specific item content depending on user context (different languages and currencies). Also some items can contain more than one article in a list and some only one. That's why I made the isSingle() method. Of course the articles list is configured to be lazily loaded.
@Stateful @Name("itemHdl") @AutoCreate public class ItemHandlerBean implements ItemHandler { @In(required = false) @Out(required = false) private Item item; private Article selArt; @Logger private Log log; @In private OrderHome orderHome; @In private SessionHandler sessionHdl; @In private FacesMessages facesMessages; @In private EntityManager entityManager; (...) // This method triggers the loading of articles list public boolean isSingle() { return item.getArticles().size() == 1; } (...)
Here is the part of my page with the datagrid
<rich:dataGrid id="browseAllSize" columns="3" elements="6" value="#{items}" var="item" styleClass="productList"> <h:commandLink action="#{browseHdl.itemSelected}"> <h:graphicImage value="/data/products/#{item.style.collection.ref}/thumb/#{itemHdl.ref}.jpg" styleClass="thumb" /> </h:commandLink> <div><h:commandButton image="/layout/img/#{messages['plist.button.add2bag1']}" action="#{itemHdl.addToBag}" styleClass="button" rendered="#{itemHdl.single}"> </h:commandButton></div> (...) </rich:dataGrid>
This give a Lazy initialization exception (transaction is not active) when fetching the isSingle value in the rendered attribute of the commandButton.
If I change the code to this
<rich:dataGrid id="browseAllSize" columns="3" elements="6" value="#{items}" var="item" styleClass="productList"> #{itemHdl.single?'single':'multiple'} <!-- new line added --> <h:commandLink action="#{browseHdl.itemSelected}"> <h:graphicImage value="/data/products/#{item.style.collection.ref}/thumb/#{itemHdl.ref}.jpg" styleClass="thumb" /> </h:commandLink> <div><h:commandButton image="/layout/img/#{messages['plist.button.add2bag1']}" action="#{itemHdl.addToBag}" styleClass="button"> <!-- No more rendered attribute --> </h:commandButton></div> (...) </rich:dataGrid>
everything is fine. I keep fetching isSingle in an el test but no more in a rendered attribute.
I'm not a specialist in JSF life cycle but I guess that rendered value are not evaluated in the same phase than pure el content. Could someone explain why this doesn't work and how to use a method trigering lazy loading in a rendered attribute or what I did wrong ?
Thank you very much.
Antoine