Dúvidas sobre comportamentos do VRaptor[Resolvido]
11 respostas
worldsoft
Olá galera, estou com uma pequena dúvida:
Tenho uma aplicação que usa hibernate, e eu controlo a abertura e fechamento das trasações em um @Interceptor do vraptor, o problema é que quando executo um delete por exemplo, numa linha de uma tabela que faz referencia a outra tabela é gerado uma ConstraintViolationExecption–Acho que é esse o nome–, até ai tudo bem pois consigo capturar essa exception e trata-la, o problema é que não estou conseguindo enviar a view uma mensagem para o usuário dizendo que a linha está sendo referenciada a uma outra tabela, pois o vraptor já escreveu e commito o response da requisição.
Ex:
Obs.: Não tenho a classe toda aqui, e também não me lembro de todos os comandos de cabeça mais o problema é +/- isso:
o seu interceptor só commita a transação depois que a view foi mostrada. E o erro só acontece no commit da transação, então já não há mais nada que pode ser feito.
Um jeito de resolver isso é criar dois interceptors, um que roda antes do controller (e da begin na tx), e um que roda logo depois do controller (antes de mostrar a view e dá commit na tx). Tb vai ser preciso colocar um redirect listener, pra dar commit na tx assim que acontecer um redirect tb.
essa solução parece boa pra vc? quer ajuda pra implementá-la?
worldsoft
Serve sim, se você poder me ajudar eu ficaria agradeçido…
Lucas_Cavalcanti
se vc sempre segue o padrão Redirect after post (ou seja, sempre que alterar algo no banco usar POST, e dar um redirect no final do método), dá pra implementar isso de um jeito mais fácil.
receba um MutableResponse do VRaptor no construtor do controller e faça:
assim antes de fazer o redirect o vraptor vai chamar o listener e commitar a transação, e vai dar o erro antes do VRaptor executar o redirect de fato e vc vai conseguir capturar a exceção no momento certo
worldsoft
Lucas Cavalcanti:
se vc sempre segue o padrão Redirect after post (ou seja, sempre que alterar algo no banco usar POST, e dar um redirect no final do método), dá pra implementar isso de um jeito mais fácil.
receba um MutableResponse do VRaptor no construtor do controller e faça:
assim antes de fazer o redirect o vraptor vai chamar o listener e commitar a transação, e vai dar o erro antes do VRaptor executar o redirect de fato e vc vai conseguir capturar a exceção no momento certo
Desta forma no catch eu consigo incluir valores para ser apresentado na view, tipo:
try{Transactiontx=this.session.beginTransaction();response.addRedirectListener(newRedirectListener(){publicvoidbeforeRedirect(){tx.commit();}});stack.next(method,instance);if(tx.isActive)tx.commit();}catch(ConstraintViolationExceptioncvEx){result.include(newValidationMessages(Arrays.asList("Erro ao deletar linha!"));if(tx.isActive)tx.rolback();}
Lucas_Cavalcanti
consegue, mas vc vai ter que redirecionar o request pra algum lugar, ele não vai fazer isso automaticamente…
dá pra tentar pegar a lógica que vc configurou no validator, isso é suficiente?
worldsoft
Lucas Cavalcanti:
consegue, mas vc vai ter que redirecionar o request pra algum lugar, ele não vai fazer isso automaticamente…
dá pra tentar pegar a lógica que vc configurou no validator, isso é suficiente?
Sim, acho que isso resolve o meu problema, vou testar a noite quando chegar em casa, e posto a resposta…
Por enquando, obrigado pela ajuda.
worldsoft
worldsoft:
Lucas Cavalcanti:
consegue, mas vc vai ter que redirecionar o request pra algum lugar, ele não vai fazer isso automaticamente…
dá pra tentar pegar a lógica que vc configurou no validator, isso é suficiente?
Sim, acho que isso resolve o meu problema, vou testar a noite quando chegar em casa, e posto a resposta…
Por enquando, obrigado pela ajuda.
Lucas funcionou tudo beleza, obrigado pela ajuda.
worldsoft
Lucas Cavalcanti:
consegue, mas vc vai ter que redirecionar o request pra algum lugar, ele não vai fazer isso automaticamente…
dá pra tentar pegar a lógica que vc configurou no validator, isso é suficiente?
Lucas deixa eu te encher o saco mais um pouco, cara não estou conseguindo pegar as exceções correta, por exemplo:
Digamos que dois usuários ao mesmo tempo tenta excluir a mesma linha no banco de dados,sei que o hibernate executa uma requisição por vez e --ai vem o problema-- não consigo pegar a exception correta que seria ObjectNotFoundException para a segunda requisição, pois a exception principal que chega até o meu bloco cacth é um InteceptionException, o que devo fazer para resolver esse pequeno problema?
worldsoft
Essa é stack trace apresentada:
br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [br.com.tsoftnet.atlas.administration.models.City#8]
at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:96)
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.tsoftnet.atlas.persistence.Filter.Persistence.intercept(Persistence.java:78)
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.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.tsoftnet.atlas.infrastructure.view.AccessManager.intercept(AccessManager.java:43)
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.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:89)
at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
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.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.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.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
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.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:23)
at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
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:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [br.com.tsoftnet.atlas.administration.models.City#8]
at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:435)
at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:189)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:178)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.engine.StatefulPersistenceContext.unproxyAndReassociate(StatefulPersistenceContext.java:619)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:89)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:73)
at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:956)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:934)
at br.com.tsoftnet.atlas.persistence.DaoGeneric.delete(DaoGeneric.java:55)
at br.com.tsoftnet.atlas.administration.controller.CityController.delete(CityController.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:61)
... 49 more
Lucas_Cavalcanti
vc pode tentar dar try…catch(ONFE e) dentro do controller ou do dao.
Lucas desculpa meu amadorismo, agora eu entendi como está funcionando está rotina que você me ajudou a implementar, o commit da transação está acontecendo antes que eu mande redirecionar para algum lugar, por isso consigo pegar alguma exceção do hibernate dentro do controler…