[Vraptor] Lazy Initialization no Interceptor

Olá pessoal,

Tenho um componente que guarda o usuário logado

[code]@Component
@SessionScoped
public class Auth {

private Paciente paciente;
...

}[/code]
E tenho também um inceptor que precisa fazer acessos ao banco de dados:

[code]@Intercepts(after = HibernateInterceptor.class)
public class DaoInterceptor implements Interceptor {

private final Result result;
private final Auth auth;
private final ConvenioDao convenioDao;

public DaoInterceptor(Result result, Auth auth, ConvenioDao convenioDao) {
	this.result = result;
	this.auth = auth;
	this.convenioDao = convenioDao;
}

public boolean accepts(ResourceMethod method) {
	return true;
}

public void intercept(InterceptorStack stack, ResourceMethod method,
		Object instance) throws InterceptionException {

	LinkedHashMap<Convenio, Boolean> convenios = new LinkedHashMap<Convenio, Boolean>();
	boolean logado = auth.isLogado()
			&& auth.getPaciente().getConvenios() != null;

	for (Convenio convenio : convenioDao.visualizar()) {
		if (logado) {
			convenios.put(convenio, auth.getPaciente().getConvenios()
					.contains(convenio));
		} else {
			convenios.put(convenio, false);
		}
	}

	result.include("convenios", convenios);
	stack.next(method, instance);
}

}[/code]
Porém, ao fazer auth.getPaciente().getConvenios(), o Hibernate tenta fazer uma LazyInitialization e dá o seguinte erro:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.metamorfosevirtual.models.Paciente.convenios, could not initialize proxy - no Session at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566) at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186) at org.hibernate.collection.internal.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:293) at org.hibernate.collection.internal.PersistentBag.contains(PersistentBag.java:256) at br.com.metamorfosevirtual.interceptors.DaoInterceptor.intercept(DaoInterceptor.java:42) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:67) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.metamorfosevirtual.interceptors.AuthInterceptor.intercept(AuthInterceptor.java:33) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.metamorfosevirtual.interceptors.HibernateInterceptor.intercept(HibernateInterceptor.java:27) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44) at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:93) at br.com.caelum.vraptor.ioc.guice.GuiceProvider.provideForRequest(GuiceProvider.java:82) at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:99) 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:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 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:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) 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:1002) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
Pelo que eu entendi, o problema seria a falta de uma session do Hibernate. Mas eu achei isso estranho, já que eu recebo um ConvenioDao no construtor do meu interceptor, e esse Dao recebe uma Session do Hibernate no seu construtor. O que pode estar causando esse problema?

O problema é que a instancia de Paciente que está guardada na classe Auth não foi totalmente carregada.
O fluxo é o seguinte:

[list]O hibernate abre a session “A”[/list]
[list]Pela session “A” você pega um paciente e coloca em Auth[/list]
[list]A session “A” é fechada (ou seja, a instancia ainda existe)[/list]
[list]O hibernate abre a session “B”[/list]
[list]Você tenta acessar uma informação que está em um Paciente[/list]
[list]O hibernate tenta usar a session “A” que está guardada junto com a instancia de Paciente para carregar o restante[/list]
[list]A session “A” está fechada, exception.[/list]

Ou seja, não use entidades em @SessionScoped, mas sim os valores que você precisa. Algo assim:

class AuthPaciente {
   private final Long id;
   private final String name;
   private final AuthConvenio convenio;

   public AuthPaciente(Paciente paciente) {
      id = paciente.getId();
      name = paciente.getName();
      convenio = new AuthConvenio(paciente.getConvenio());
   }

   // getters
}

@SessionScoped
class Auth {
   private AuthPaciente paciente;

   public void load(Paciente paciente) {
      this.paciente = new AuthPaciente(paciente);
   }

   // é interessante usar a lei de Demeter aqui... Ou seja, ao invés de fazer um getPaciente(), fazer um getPacienteId() e um getPacienteName()
}

Esse post mostra o problema e dá 4 soluções: http://uaihebert.com/?p=1367

Hmm entendi. Já corrigi aqui e funcionou.
Valeu pessoal!