Problemas com Hibernate + Vraptor

Eu tenho 2 factories: uma pra HibernateSessionFactory e outra pra HibernateSession. Segue o código delas:

HibernateSession:

[code]@Component
public class HibernateSession implements ComponentFactory {

private SessionFactory factory;
private Session session;

public HibernateSession(SessionFactory factory) {
	this.factory = factory;
}

@PostConstruct
public void construtor() {
	this.session = factory.openSession();
}

public Session getInstance() {
	return this.session;
}

@PreDestroy
public void destrutor() {
	this.session.close();
}

}[/code]

HibernateSessionFactory:

[code]@Component
public class HibernateSessionFactory implements
ComponentFactory {

private SessionFactory factory;

@PostConstruct
public void construtor() {
	Configuration configuration = new Configuration();
	configuration.configure();

	ServiceRegistryBuilder builder = new ServiceRegistryBuilder();
	ServiceRegistryBuilder settings = builder.applySettings(configuration
			.getProperties());
	ServiceRegistry serviceRegistry = settings.buildServiceRegistry();
	this.factory = configuration.buildSessionFactory(serviceRegistry);
}

public SessionFactory getInstance() {
	return this.factory;
}

@PreDestroy
public void destrutor() {
	this.factory.close();
}

}[/code]

Além disso, eu tenho um interceptor com o objetivo de abrir e terminar a transação do hibernate:

[code]@Intercepts
public class HibernateInterceptor implements Interceptor {

private final Session session;

public HibernateInterceptor(Session session) {
	this.session = session;
}

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

public void intercept(InterceptorStack stack, ResourceMethod method,
		Object instance) throws InterceptionException {
	session.getTransaction().begin();
	stack.next(method, instance);
	session.getTransaction().commit();
}

}[/code]

Minha ideia é fazer o acesso ao banco de dados através de um DAO:

[code]@Component
public class Dao {

private final Session session;

public Dao(Session session) {
	this.session = session;
}

public List getAll(String classe) {
	Query query = session.createQuery("from " + classe);
	return query.list();
}

}[/code]

Só que tem 2 problemas com esse código todo:
1- Apesar do meu controller só chamar o “getAll” do DAO 1 vez, ele está sendo executado 2 vezes, em momentos distintos.
2- O destrutor da HibernateSession não está sendo executado corretamente. Uma mensagem é disparada no console:

Alguém sabe o motivo e a solução desses problemas?

Ah, acabei de perceber que quando faço uma requisição, o método do controller é executado 2 vezes. Porque isso?

Curioso é que eu descobri que eu estava com 2 jars do Vraptor no projeto. Aí eu removi 1 deles e dei clean no servidor e no projeto, mas mesmo assim continua passando 2 vezes pelo controller ao fazer 1 única requisição.

Bem, agora o problema das 2 execuções se resolveu sozinho, não entendi porque oO

Mas ainda continuo com o problema do destrutor. Eu removi umas libs que coloquei por engano no projeto e agora a seguinte stack trace está sendo impressa no console:

01:26:38,735 WARN [RequestCustomScope ] Error while invoking PreDestroy net.vidageek.mirror.exception.ReflectionProviderException: Could not invoke method destrutor at net.vidageek.mirror.provider.java.PureJavaMethodReflectionProvider.invoke(PureJavaMethodReflectionProvider.java:45) at net.vidageek.mirror.invoke.MethodHandlerByMethod.withArgs(MethodHandlerByMethod.java:54) at net.vidageek.mirror.invoke.MethodHandlerByMethod.withoutArgs(MethodHandlerByMethod.java:58) at br.com.caelum.vraptor.ioc.guice.ScopeLifecycleListener$LifecycleExecutor$1.onEvent(ScopeLifecycleListener.java:94) at br.com.caelum.vraptor.ioc.guice.RequestCustomScope.stop(RequestCustomScope.java:75) at br.com.caelum.vraptor.ioc.guice.GuiceProvider.provideForRequest(GuiceProvider.java:84) 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:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:127) at org.hibernate.internal.SessionFactoryImpl.getStatisticsImplementor(SessionFactoryImpl.java:1482) at org.hibernate.internal.SessionFactoryImpl.getStatistics(SessionFactoryImpl.java:1478) at org.hibernate.internal.SessionImpl.close(SessionImpl.java:348) at br.com.metamorfosevirtual.factories.HibernateSession.destrutor(HibernateSession.java:33) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at net.vidageek.mirror.provider.java.PureJavaMethodReflectionProvider.invoke(PureJavaMethodReflectionProvider.java:38) ... 22 more

vc tem no arquivo de configuração do hibernate alguma menção ao statistics?

Não. Coloquei só as configurações do banco e os mapeamentos das classes de modelo.

org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]

alguém tá tentando usar isso no código.

Mas quando eu comento a linha “session.close()” não dá esse erro. Se alguém tivesse tentando usar não seria pra dar o erro do mesmo jeito?

Caused by: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]  
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:127)  
    at org.hibernate.internal.SessionFactoryImpl.getStatisticsImplementor(SessionFactoryImpl.java:1482)  
    at org.hibernate.internal.SessionFactoryImpl.getStatistics(SessionFactoryImpl.java:1478)  
    at org.hibernate.internal.SessionImpl.close(SessionImpl.java:348)  
    at br.com.metamorfosevirtual.factories.HibernateSession.destrutor(HibernateSession.java:33)  

o erro acontece justo na hora de dar o close na session… deve ser a hora em que ele coleta as estatísiticas de fato…

Esse erro não parece ter a ver com o VRaptor e sim com as configurações do Hibernate…

crie uma classe com um método main onde vc abre uma session e depois fecha, pra ver se dá o mesmo erro.

Fiz o teste o não deu o erro. Aí eu tive a ideia de fechar a Factory antes de fechar a Session. E deu exatamente o mesmo erro. Agora tudo faz sentido. O problema é que o Vraptor tá chamando o destrutor da Factory antes da session. Tem como forçar ele a destruir a session antes da factory?

A factory NÃO deveria ser fechada a todo request…

muda o componente que cria e fecha a SessionFactory para ser @ApplicationScoped e o problema vai resolver.

Ih é, bem observado. Agora funcionou :slight_smile:
Obrigado Lucas.