views:

89

answers:

2

Hello In a Spring application, I use the component rich: tree with Hibernate which display the hierarchy of applications using lazy loading. The problem is that the Hibernate session is closed which prevent lazy loading and i receive exception when the page is rendered. Finally I added opensessionViewFilter that's allows me to keep the session until the page is rendered.

<filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>sessionFactory</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

this solution solved the problem partially the page is rendered and the rich:Tree component is displayed but when ajax calls are made (navigation between nodes) I got the same error of lazy loading:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: myPackage.entities.Module.modules, no session or session was closed
 at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
 at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
 at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
 at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
 at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
 at com.cylande.utilities.TreeNode.getNodes(TreeNode.java:77)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at javax.el.BeanELResolver.getValue(BeanELResolver.java:62)
 at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:54)
 at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
 at org.apache.el.parser.AstValue.getValue(AstValue.java:118)
 at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
 at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
 at org.richfaces.component.html.HtmlRecursiveTreeNodesAdaptor.getNodes(HtmlRecursiveTreeNodesAdaptor.java:160)
 at org.richfaces.component.UIRecursiveTreeNodesAdaptor$1.getData(UIRecursiveTreeNodesAdaptor.java:74)
 at org.richfaces.model.StackingTreeModel.getDataModel(StackingTreeModel.java:80)
 at org.richfaces.model.StackingTreeModel.isEmpty(StackingTreeModel.java:107)
 at org.richfaces.model.StackingTreeModel.isLeaf(StackingTreeModel.java:264)
 at org.richfaces.component.UITree.isLeaf(UITree.java:534)
 at org.richfaces.renderkit.html.TreeNodeRenderer.doEncodeBegin(TreeNodeRenderer.java:105)
 at org.richfaces.renderkit.html.TreeNodeRenderer.doEncodeBegin(TreeNodeRenderer.java:86)
 at org.ajax4jsf.renderkit.RendererBase.encodeBegin(RendererBase.java:100)
 at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:813)
 at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:275)
 at org.richfaces.renderkit.TreeRendererBase$DataVisitorWithLastElement.process(TreeRendererBase.java:255)
 at org.richfaces.model.AbstractTreeDataModel.processElement(AbstractTreeDataModel.java:111)
 at org.richfaces.model.StackingTreeModel.doWalk(StackingTreeModel.java:294)
 at org.richfaces.model.StackingTreeModel$Visitor1.process(StackingTreeModel.java:416)
 at org.richfaces.model.StackingTreeModel$ShiftingDataVisitor.end(StackingTreeModel.java:461)
 at org.richfaces.model.StackingTreeModel.doWalk(StackingTreeModel.java:348)
 at org.richfaces.model.StackingTreeModel.walk(StackingTreeModel.java:383)
 at org.richfaces.component.UITree.walk(UITree.java:422)
 at org.richfaces.renderkit.TreeRendererBase.writeContent(TreeRendererBase.java:683)
 at org.richfaces.renderkit.TreeRendererBase.encodeAjaxChildren(TreeRendererBase.java:475)
 at org.ajax4jsf.component.UIDataAdaptor.encodeAjaxChild(UIDataAdaptor.java:454)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:146)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
 at org.ajax4jsf.renderkit.AjaxContainerRenderer.encodeAjax(AjaxContainerRenderer.java:123)
 at org.ajax4jsf.component.AjaxViewRoot.encodeAjax(AjaxViewRoot.java:680)
 at org.ajax4jsf.component.AjaxViewRoot.encodeChildren(AjaxViewRoot.java:551)
 at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930)
 at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
 at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
 at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
 at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
 at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
 at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
 at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
 at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)
 at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:70)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
 at java.lang.Thread.run(Thread.java:619)

Please can you help me to lazy load list for an ajax component.

here is my xhtml page:

<h:form>
            <rich:panel>
                <rich:tree>
                    <rich:recursiveTreeNodesAdaptor roots="#{treeBean.srcRouts}"
                        var="item" nodes="#{item.nodes}">
                    </rich:recursiveTreeNodesAdaptor>
                </rich:tree>
            </rich:panel>

</h:form>

Here is the Bean:TreeBean.java

public class TreeBean {
private List<TreeNode> srcRouts;
@Autowired
private ApplicationDAO applicationDAO;
@Transactional
public List<TreeNode> getSrcRouts() {
    List<TreeNode> ListNode=new ArrayList<TreeNode>();
    if(srcRouts==null)
    {
        List<Application> list=applicationDAO.findAll();
        for(Application app:list)
        {
            TreeNode treeNode=new TreeNode();
            treeNode.setApplication(app);
            ListNode.add(treeNode);
        }
        srcRouts=ListNode;
    }
    return srcRouts;
}

public void setSrcRouts(List<TreeNode> srcRouts) {
    this.srcRouts = srcRouts;
}
}

Here is the Bean TreeNode.java:

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import myPackage.entities.Application;
import myPackage.entities.Module;
import myPackage.entities.Page;
import myPackage.services.ApplicationDAO;

public class TreeNode {
    private List<TreeNode> nodes;
    private ApplicationDAO applicationDAO;
    private String libelle;
    private Application application;
    private Module module;
    private Page page;

    public Application getApplication() {
        return application;
    }

    public void setApplication(Application application) {
        this.application = application;
    }

    public Module getModule() {
        return module;
    }

    public void setModule(Module module) {
        this.module = module;
    }

    public Page getPage() {
        return page;
    }

    public void setPage(Page page) {
        this.page = page;
    }

    public String getLibelle() {
        return libelle;
    }

    public void setLibelle(String libelle) {
        this.libelle = libelle;
    }

    public ApplicationDAO getApplicationDAO() {
        return applicationDAO;
    }

    public void setApplicationDAO(ApplicationDAO applicationDAO) {
        this.applicationDAO = applicationDAO;
    }

    public List<TreeNode> getNodes() {
        List<TreeNode> listNoeud = new ArrayList<TreeNode>();
        Set<Module> setModule;
        Set<Page> setPage;
        if (nodes == null) {
            // noeud application
            if (application != null) {
                setModule = this.application.getModules();
                for (Module module : setModule) {
                    if(module.getModule()==null){
                    TreeNode treeNode = new TreeNode();
                    treeNode.module = module;
                    listNoeud.add(treeNode);
                }
                }
            }
            // noeud module
            else if (module != null) {
                setModule = this.module.getModules();
                for (Module module : setModule) {
                    TreeNode treeNode = new TreeNode();
                    treeNode.module = module;
                    listNoeud.add(treeNode);
                }
                setPage = this.module.getPages();
                for (Page page : setPage) {
                    TreeNode treeNode = new TreeNode();
                    treeNode.page = page;
                    listNoeud.add(treeNode);
                }
            }
            nodes=listNoeud;
        }

        return nodes;
    }

    public void setNodes(List<TreeNode> nodes) {
        this.nodes = nodes;
    }

    public String toString() {
        String libelle="";

        // noeud application
        if (application != null) {
            libelle = application.getNomApplication();
        }
        // noeud module
        else if (module != null) {
            libelle = module.getNomModule();
        }
        // noeud page
        else if (page != null) {
            libelle = page.getNomPage();
        }
        return libelle;
    }
}

I use the component tree to display the applications added by the user to be tested ...In fact try to create an application that's run tests chosen by the user. to specify, a node for me is an application, a module or a page

Here is my Generic DAO:

import java.io.Serializable;
import java.util.List;

import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class GenericDAOHibernateImpl<T, PK extends Serializable> implements
        GenericDAO<T, PK> {
    private Class<T> type;
    @Autowired
    private HibernateTemplate hibernateTemplate;

    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

    public GenericDAOHibernateImpl(Class<T> type) {
        this.type = type;
    }

    public PK create(T o) {
        return (PK) getHibernateTemplate().save(o);
    }

    public T read(PK id) {
        return (T) getHibernateTemplate().get(type, id);
    }

    public void update(T o) {
        getHibernateTemplate().update(o);
    }

    public void delete(T o) {
        getHibernateTemplate().delete(o);
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        List<T> toExport = null;
        toExport = (List<T>) getHibernateTemplate().find(
                "from "+ type.getName());
        return toExport;
    }

    @SuppressWarnings("unchecked")
    public T findByID(PK id) {
        T entity = null;
        entity =  (T)getHibernateTemplate().get(type, id);
        return entity;
    }

}

thank you in advance for your help.

+2  A: 

You have at least two options

  • define the collection (*ToMany) with fetchType=FetchType.EAGER
  • manually initialize the object before 'sending' it to the view with Hibernate.initialize(..)
Bozho
is it not possible use do lazy loading in that case?
@user405458 - it is possible but you need to initialize it in the bean before "sending" it to the view
Odelya
well, the `OpenSessionInView` should work. But perhaps the details you've given are not enough to see why it isn't
Bozho
How can OSIV work once the view has been rendered?
Pascal Thivent
@Pascal, I have used something like OpenEntityManagerInView with a tree, and it worked. Of course you'd have to reload the entities..
Bozho
I must be missing something about the way this component works. I'm confused.
Pascal Thivent
@Pascal - it has three modes, to start with - client side, server side and ajax. It's not clear which one he is using ("ajax calls" can happen from any event on the tree). Then, with ajax-mode, server-side data (from the managed bean) is obtained (via JSON, but that's hidden), and is rendered. Here the scope of the bean also comes into play. That's why I said there were not enough details - If we see the code of the managed bean, and the mode of the tree, more could be said.
Bozho
Interesting. I'll take a deeper look, I'm curious now and I really want to understand. Thanks a lot for the details.
Pascal Thivent
+2  A: 

I don't have any particular experience with the rich:tree component but options are IMO:

  1. get child nodes via some DAO method for a given parent node id.
  2. use some kind of "remote lazy loading".
  3. don't use lazy loading.

I don't consider #3 to be a "solution".

For #2, have a look at H3T (read carefully).

To implement #1, the Dynamic Trees in JSF post could help. This would be my choice.

Further reading

Pascal Thivent
I wouldn't recommend #3. performance wise.
Odelya
it depends on the size. If you don't expect to have more than ten items, why worry about performance. I, for example, have used rich:tree with eager collections, knowing that the items cannot exceed 100 in the worst case.
Bozho
@Odelya @Bozho I agree with both :) It indeed depends on the size, the depth of the tree, if the structure is recursive, etc. But I'll dig this to find out the truth when you actually do want lazy loading.
Pascal Thivent
I already tried #3 and it works, but given the amount of data I prefer to make lazy loading to not affect performance.