Hibernate + JSF + Primefaces = lazily initialize

Ola bom dia,

Tenho um filtro configurado para open session do hibernate seguindo alguns passos que achei aqui no forum, porem qdo carrego um list dentro de um <p:dialog> ocorre o erro:

11:35:14 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: br.com.casavet.dominio.Fornecedor.contato, no session or session was closed

Já li documentação do proprio Hibernate, fiz modificações no filtro e utilizei outros modelos porem sem sucesso. O Bean ta como @SessionScoped.

Filter

[code]
@WebFilter("/HibernateSessionFilter")
public class HibernateSessionFilter implements Filter {

public HibernateSessionFilter() { }


public void destroy() {	}


public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

	HibernateUtil.openSession();   
    try {   
        HibernateUtil.currentSession().beginTransaction();   
        
        chain.doFilter(request, response);
        
        HibernateUtil.currentSession().getTransaction().commit();   
    } catch (Exception e) {
    	
    	e.printStackTrace();

        throw new ServletException(e);   
        
    } finally {   
        HibernateUtil.closeCurrentSession(); 
    }  

}


public void init(FilterConfig fConfig) throws ServletException {}

}[/code]

HibernateUtil

[code]public class HibernateUtil {

private static SessionFactory sessionFactory;   
private static ThreadLocal&lt;Session&gt; sessions = new ThreadLocal&lt;Session&gt;();   
   
static {   
    AnnotationConfiguration configuration = new AnnotationConfiguration();   
    configuration.configure();   
    sessionFactory = configuration.buildSessionFactory();   
}   
   
public static Session openSession(){   
    Session session = sessionFactory.openSession();   
    sessions.set(session);   
    return sessions.get();   
}   
   
public static Session currentSession(){   
    return sessions.get();   
}   
   
public static void closeCurrentSession(){   
    sessions.get().close();   
    sessions.set(null);   
}   
   
public static void clearSession(){   
    sessions.get().clear();   
}   
   
public static void flushSession(){   
    sessions.get().flush();   
}   
   
public static void rollback(){   
    sessions.get().getTransaction().rollback();   
    sessions.get().getTransaction().begin();   
} 

} [/code]

Web.xml

&lt;filter&gt; &lt;display-name&gt;HibernateSessionFilter&lt;/display-name&gt; &lt;filter-name&gt;HibernateSessionFilter&lt;/filter-name&gt; &lt;filter-class&gt;br.com.casavet.filter.HibernateSessionFilter&lt;/filter-class&gt; &lt;/filter&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;HibernateSessionFilter&lt;/filter-name&gt; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; &lt;/filter-mapping&gt;

Hibernate.cfg.xml

&lt;property name="hibernate.connection.driver_class"&gt;com.mysql.jdbc.Driver&lt;/property&gt; &lt;property name="hibernate.connection.url"&gt;jdbc:mysql://localhost/casavet&lt;/property&gt; &lt;property name="hibernate.connection.username"&gt;root&lt;/property&gt; &lt;property name="hibernate.connection.password"&gt;&lt;/property&gt; &lt;property name="hibernate.show_sql"&gt;false&lt;/property&gt; &lt;property name="hibernate.format_sql"&gt;true&lt;/property&gt; &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.MySQLInnoDBDialect&lt;/property&gt; &lt;property name="hibernate.hbm2ddl.auto"&gt;update&lt;/property&gt; &lt;property name="hibernate.current_session_context_class"&gt;thread&lt;/property&gt;

Fornecedor

@OneToMany(cascade = CascadeType.ALL, mappedBy = "fornecedorId", fetch = FetchType.LAZY) private List&lt;Contato&gt; contato;

Contato

@JoinColumn(name = "fornecedorId", referencedColumnName = "fornecedorId") @ManyToOne(optional = false, fetch = FetchType.LAZY) private Fornecedor fornecedorId;

Datatable Fornecedor

[code] <p:dataTable id=“fr” var=“fr” value="#{fornecedorBean.listaFornecedor}"
paginator=“true” rows=“10” paginatorPosition=“bottom”
rowsPerPageTemplate=“10,15,20”
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" >

			    &lt;p:column headerText="CNPJ"&gt;
			        #{fr.fornecedorCNPJ}
			    &lt;/p:column&gt;
			
			    &lt;p:column headerText="Nome"&gt;
			        #{fr.fornecedorNome}
			    &lt;/p:column&gt;
			    
		       &lt;p:column headerText="Contatos" style="width:60px"&gt;
		       
	            	&lt;p:commandLink action="#{fornecedorBean.abrirContato}" 
	            			oncomplete="telaContato.show()"
	            			update="@form" async="true"&gt;
	            		&lt;span class="ui-icon ui-icon-person"&gt;&lt;/span&gt;
	            	&lt;/p:commandLink&gt;
				            				            
		       &lt;/p:column&gt; 				    
			
			&lt;/p:dataTable&gt;[/code]

Dialog Datatable Contatos

[code]<p:dialog id=“addContatoDialog” modal=“true”
header=“Casa Vet: Lista Contatos - Fornecedor: #{fornecedorBean.fornecedor.fornecedorNome}”
widgetVar=“telaContato” width=“600”>

			&lt;p:dataTable id="con" var="con" value="#{fornecedorBean.fornecedor.contatos}" 
						paginator="true" rows="10" paginatorPosition="bottom"
						rowsPerPageTemplate="10,15,20" 
						paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"  &gt;

			    
				        &lt;p:column headerText="Nome"&gt;  
				                    &lt;h:outputText value="#{con.contatoNome}" /&gt;  
				        &lt;/p:column&gt;
				        
			&lt;/p:dataTable&gt;			

   
	    &lt;/p:dialog&gt;	[/code]

Preciso aprender usar isto, se alguem puder dar uma luz, vlws.

Fábio

Esse post vai te ajudar a entender esse problema e as possíveis soluções: Quatro soluções para LazyInitializationException.

Ola Jakefrog,

O problema até entendi, e as soluções tb. Com join query ou com FetchType.EAGER funciona ok.

O problema está com Open Session in View com filtro. Já tentei implementar de diversos exemplos diferentes.

Só funciona se eu utilizar @RequestScoped no lugar de @SessionScoped.

A duvida é não tem como implementar com SessionScoped?

[quote=fabiolima]Ola Jakefrog,

O problema até entendi, e as soluções tb. Com join query ou com FetchType.EAGER funciona ok.

O problema está com Open Session in View com filtro. Já tentei implementar de diversos exemplos diferentes.

Só funciona se eu utilizar @RequestScoped no lugar de @SessionScoped.

A duvida é não tem como implementar com SessionScoped? [/quote]Cara, nunca ouvi lazy exception acontecer com open session in view apenas com SessionScoped viu.

Bizarro.

Eu sempre uso namedQuery, então ñ passo por isso. [=

Vamos ver se alguém aqui já passou por isso. [=

Com este modelo de Filter dá pra ver que ele está sendo executado, veja o erro.

Filter:

[code]
public void destroy() { }

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

	
	
	System.out.println("\n************************************************************************************ openSession()");
	HibernateUtil.openSession();   
    try {   
        
    	System.out.println("\n**************************** currentSession().beginTransaction() = isConnected: " + HibernateUtil.currentSession().isConnected());
    	HibernateUtil.currentSession().beginTransaction();   
        
    	System.out.println("\n********************************** chain.doFilter =  isConnected: " + HibernateUtil.currentSession().isConnected());
    	chain.doFilter(request, response);
        
    	
    	System.out.println("\n********************************** currentSession().getTRansaction().commit() =  isConnected: " + HibernateUtil.currentSession().isConnected());
        HibernateUtil.currentSession().getTransaction().commit();   
    } catch (Exception e) {
    	
    	e.printStackTrace();

        throw new ServletException(e);   
        
    } finally {   
        HibernateUtil.closeCurrentSession();
        
        System.out.println("\n********************************************************************************** closeCurrentSession() \n\n");
    }  

}


public void init(FilterConfig fConfig) throws ServletException {}[/code]

Erro:


************************************************************************************ openSession()

********************************** currentSession().beginTransaction() = isConnected: true

********************************** chain.doFilter =  isConnected: true
10:15:48 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: br.com.casavet.dominio.Fornecedor.contatos, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.casavet.dominio.Fornecedor.contatos, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
	at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
	at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
	at javax.faces.model.ListDataModel.isRowAvailable(ListDataModel.java:106)
	at javax.faces.model.ListDataModel.setRowIndex(ListDataModel.java:181)
	at javax.faces.model.ListDataModel.setWrappedData(ListDataModel.java:216)
	at javax.faces.model.ListDataModel.<init>(ListDataModel.java:75)
	at javax.faces.component.UIData.getDataModel(UIData.java:1284)
	at javax.faces.component.UIData.setRowIndex(UIData.java:447)
	at javax.faces.component.UIData.iterate(UIData.java:1407)
	at javax.faces.component.UIData.processDecodes(UIData.java:980)
	at org.primefaces.component.datatable.DataTable.processDecodes(DataTable.java:571)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
	at org.primefaces.component.dialog.Dialog.processDecodes(Dialog.java:348)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
	at org.primefaces.component.panel.Panel.processDecodes(Panel.java:277)
	at javax.faces.component.UIForm.processDecodes(UIForm.java:212)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
	at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:920)
	at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:74)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at br.com.casavet.filter.HibernateSessionFilter.doFilter(HibernateSessionFilter.java:38)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)


********************************** currentSession().getTRansaction().commit() =  isConnected: true

********************************************************************************** closeCurrentSession() 

E se eu coloco a datatable de contatos dentro da datatable fornecedor funciona normal, igual esta abaixo esta funcionando. Só nao funciona com commandlink para openDialog.

[code]
<p:dataTable id=“fr” var=“fr” value="#{fornecedorBean.listaFornecedor}"
paginator=“true” rows=“10” paginatorPosition=“bottom”
rowsPerPageTemplate=“10,15,20”
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
>

			    <p:column headerText="CNPJ">
			        #{fr.fornecedorCNPJ}
			    </p:column>
			
			    <p:column headerText="Nome">
			        #{fr.fornecedorNome}
			    </p:column>
			    
			    <p:column>
			    
					<p:dataTable id="con" var="con" value="#{fr.contatos}" 
								paginator="true" rows="10" paginatorPosition="bottom"
								rowsPerPageTemplate="10,15,20" 
								paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"  
					            >
	
					    
						        <p:column headerText="Nome">  
						                    <h:outputText value="#{con.contatoNome}" />  
						        </p:column>
						        
						        <p:column headerText="Telefone/Celular/Email">  
						                    <h:outputText value="#{con.contatoInfo}" />   
						        </p:column>
						        
					</p:dataTable>					    
			    </p:column>

			    
	    
			
			</p:dataTable>	[/code]

Se alguem tiver alguma dica do que pode ser, obrigado.

Quando você manda abrir o dialog, você dá um refresh no form? Pode ser isso.

Ao tentar abrir o dialog, seu filtro é chamado?

Sim Jakefrog, ao clicar no commandlink o filtro executa e ocorre o erro. Aquele print de erro que coloquei foi clicando no link.

O q vi no debug é que no objeto fornecedor a lista de contatos (PersistentBag) esta com session null.

Para testar, busquei novamente no banco o fornecedor apos clicar no commandlink, e ae a session vem preenchida e nao ocorre erro.

[code]
public void abrirContato(){

	FacesContext facesContext = FacesContext.getCurrentInstance(); 
	Map<String, Object> request = facesContext.getExternalContext().getRequestMap();		
	this.fornecedor = (Fornecedor) request.get("fr");
	

	try {
		fornecedor = fornecedorCtr.getFornecedor(fornecedor.getFornecedorId()); // pesquiso novamente o fornecedor no banco pelo ID
	} catch (FornecedorException e) {

	}
	
}[/code]

Pois é cara, ta parecendo que o ajax está processando a lista em questão após o filtro fechar. O.o

Nunca vi isso não.

Por isso q eu prefiro namedQuery. [=

Boa sorte aí.

Ola fabiolima,

Vc conseguiu resolver este problema?
Estou com a mesma questão aqui, no ajax request funciona apenas quando for @RequestScoped.

desde já agradeço…

Resolvi de outra maneira, ao abrir o Dialog faço nova consulta no banco e já pego os contatos. Dessa maneira que está aí não deu certo.

Use um PhaseListener para abrir e fechar sua sessão.

tentei com PhaseListener para controlar a sessão e tambem não funcinou nas requisições ajax.
O PhaseListener até é executado porem continua dando erro de sessão fechada.
Parece que so com @RequestScoped mesmo para funcionar.

Cara um uso em um projeto o PhaseListener e funciona sem problemas, abaixo segue meu codigo:

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.servlet.http.HttpServletResponse;
import org.hibernate.Session;

public class PhaseListener implements javax.faces.event.PhaseListener {

    @Override
    public void beforePhase(PhaseEvent event) {
        final FacesContext facesContext = event.getFacesContext();
        final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();

        if (event.getPhaseId().equals(PhaseId.RESTORE_VIEW)) {
            Session session = HibernateSessionFactory.getSession();
            /* Adiciona a requisição a sessão recuperado do hibernate**/
            FacesContextUtil.setRequestSession(session);
            System.out.println("Criou a sessão e atrelou a requisição. ");
        }

    }

    @Override
    public void afterPhase(PhaseEvent event) {
        if (event.getPhaseId().equals(PhaseId.RENDER_RESPONSE) && FacesContextUtil.getResquestSession() != null) {
            /* recupera sessão do hibernate e fecha a sessão.**/
            FacesContextUtil.getResquestSession().close();
            System.out.println("Fechou a sessão");
        }
    }

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
}

Ta ai funciona que é uma blz.

OK soh uma duvida srmachado com fica no DAO ?