Hibernate + JSF + Primefaces = lazily initialize

13 respostas
F

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
@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 {}

}
HibernateUtil
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();   
    } 

}
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
&lt;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}" &gt;
				
			
				    &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;
Dialog Datatable Contatos
&lt;p:dialog id="addContatoDialog"  modal="true"   
		                header="Casa Vet: Lista Contatos - Fornecedor: #{fornecedorBean.fornecedor.fornecedorNome}"  
		                widgetVar="telaContato" width="600"&gt;  

			
				&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;

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

Fábio

13 Respostas

H

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

F

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?

H

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?

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. [=

F

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

Filter:

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 {}

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.

<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>

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

H

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

Ao tentar abrir o dialog, seu filtro é chamado?

F

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.

[img]http://img259.imageshack.us/img259/2919/lazysr.jpg[/img]

Para testar, busquei novamente no banco o fornecedor apos clicar no commandlink, e ae a session vem preenchida e nao ocorre erro.
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) {

		}
		
	}

[img]http://img651.imageshack.us/img651/8754/lazy2w.jpg[/img]

H

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í.

R

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…

F

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.

S

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

R

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.

S

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.

R

OK soh uma duvida srmachado com fica no DAO ?

Criado 7 de junho de 2012
Ultima resposta 10 de abr. de 2013
Respostas 13
Participantes 4