Problemas com Hibernate + Vraptor

11 respostas
G

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

HibernateSession:
@Component
public class HibernateSession implements ComponentFactory<Session> {

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

}
HibernateSessionFactory:
@Component
public class HibernateSessionFactory implements
		ComponentFactory<SessionFactory> {

	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();
	}
}
Além disso, eu tenho um interceptor com o objetivo de abrir e terminar a transação do hibernate:
@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();
	}

}
Minha ideia é fazer o acesso ao banco de dados através de um DAO:
@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();
	}

}

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:

WARN [CommonAnnotationBeanPostProcessor] Invocation of destroy method failed on bean with name 'hibernateSession': org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]

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

11 Respostas

G

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

G

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.

G

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

L

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

G

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

L

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

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

G

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?

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

G

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?

L

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.

G

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

Criado 22 de novembro de 2013
Ultima resposta 26 de nov. de 2013
Respostas 11
Participantes 2