Boa tarde galera estou usando o vraptor e JPA hibernate em meu projeto sei que vraptor faz o flush sozinho e tals, só que com isso eu não consigo retornar uma mensagem para o meu usuário, daí para resolver isso eu faço o flush no metodo delete por exemplo, mas quando tenho um registro vinculado a outro ele dá uma excepetion, que acredito que depois que da a PersistenceException depois que eu forcei o flush, ele executa novamente o o commit, espero que tenho conseguido passar o meu problema.
em poucas palavras gostaria de saber como faço para não executar o commit que o vraptor faz…
segue parte do meu código:
Controller:
@Path("/excluirContador/{contador.idcontador}")
public void excluirContador(Contador contador) {
try {
...
repository.delete(contador);
} catch (PersistenceException ex) {
result.include("mensagem",
"Não é permitido excluir esse registro, esta vinculado a outro(s) registro(s)");
result.include("categoria", "erro");
} catch (Exception ex) {
result.include("mensagem",
"Ocorreu um erro inesperado, se persistir o erro, entre em contado com suporte");
result.include("categoria", "erro");
}
result.forwardTo(this).contador(paginacao.getSelecionado());
}
minha business (GenericBusiness):
public void delete(Object id) throws Exception {
try {
manager.remove(manager.getReference(clazz, id));
manager.flush();
} catch (PersistenceException persistenceException) {
manager.getTransaction().rollback();
throw new PersistenceException(" Erro ");
} catch (Exception ex) {
manager.getTransaction().rollback();
throw new Exception(" Erro ");
}
}
a exception que gera:
java.lang.IllegalStateException: Transaction not active
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:69)
at br.com.caelum.vraptor.util.jpa.JPATransactionInterceptor.intercept(JPATransactionInterceptor.java:53)
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.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.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.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.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:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:679)
não entendi o problema…
vc deu o flush depois do remove e mesmo assim não soltou exception?
vc não precisa dar rollback se estiver usando o pacote .jpa no web.xml, o VRaptor vai dar esse rollback automaticamente em caso de erro
Bom é o seguinte eu tento excluir um registro que esta vinculado a outro no momento que ele der o flush, será gerado uma exception do tipo PersistenceException certo?
se no metodo eu deixar somente assim:
manager.remove(manager.getReference(clazz, id));
...
catch (PersistenceException persistenceException) { //
throw new PersistenceException(" Erro ");
ele não gera a exception que eu quero que gere no caso PersistenceException, para que eu possa recuperar ela e enviar para o usuário que a mensagem que não pode ser excluido.
mas se eu fizer da form abaixo:
manager.remove(manager.getReference(clazz, id));
manager.flush();
...
catch (PersistenceException persistenceException) { //
throw new PersistenceException(" Erro ");
ele faz o que eu quero, só que porém ele gera a exception:
SEVERE: Servlet.service() for servlet default threw exception
javax.persistence.RollbackException: Transaction marked as rollbackOnly
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73)
at br.com.caelum.vraptor.util.jpa.JPATransactionInterceptor.intercept(JPATransactionInterceptor.java:53)
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.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.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:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:679)
pelo que eu entendi ele tenta dar o commit denovo que é o do vraptor, daí a pergunta como eu faço para deixar somente o FLUSH do meu metodo delete, ou qual a melhor forma para atender as minhas necessidades.
espero que eu tenha conseguido passar o meu problema, desculpe se esta meio confuso.
a idéia é não dar mais a exception, certo?
vc vai precisar sobrescrever o comportamento do JPATransactionInterceptor…
um dos jeitos é ignorando o RollbackException:
@Intercepts(before=JPATransactionInterceptor.class)
public class IgnoradorInterceptor implements Interceptor {
//accepts true
public void intercept(...) {
try {
stack.next(...);
} catch (RollbackException e) {
//ignora, faz um log, talvez, e NÃO relança a exception
}
}
}
esse é o mais simples, então tenta aí…
só cuidado pra não cair em casos zuados, então pelo menos faça o log da exception
Teria uma forma de eu não sobscrever o o comportamento do JPA, mas eu enviar uma mensagem para o meu usuário que não é permitido excluir o registro?
se deu o rollbackException é pq deu uma exception e vc tratou.
se eu não tratar ele não chega a dar commit, então não dá o RollbackException.
pode fazer esse Interceptor sem dó
ele vai executar sempre que vc fizer o catch em uma Exception da jpa e não relançar
Lucas eu não entendi muito bem, o que deve fazer, se você puder me explicar melhor, eu devo fazer algo do tipo:
package br.com.coliseu.util;
import javax.persistence.EntityManager;
import javax.persistence.RollbackException;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.util.jpa.JPATransactionInterceptor;
@Intercepts(before = JPATransactionInterceptor.class)
public class IgnoradorInterceptor implements Interceptor {
private final EntityManager manager;
public IgnoradorInterceptor(EntityManager manager) {
this.manager = manager;
}
public boolean accepts(ResourceMethod method) {
return true;
}
public void intercept(InterceptorStack stack, ResourceMethod method,
Object resourceInstance) throws InterceptionException {
try {
stack.next(method, resourceInstance);
} catch (RollbackException e) {
manager.getTransaction().rollback();
}
}
}
GenericBusiness
public void delete(Object id) throws Exception {
manager.remove(manager.getReference(clazz, id));
manager.flush();
}
Controller:
@Path("/excluirContador/{contador.idcontador}")
public void excluirContador(Contador contador) {
try {
paginacao.setUrl("/contador");
result.include("paginacao", paginacao);
repository.delete(contador.getIdcontador());
} catch (PersistenceException ex) {
result.include("mensagem",
"Não é permitido excluir esse registro, esta vinculado a outro(s) registro(s)");
result.include("categoria", "erro");
} catch (Exception ex) {
result.include("mensagem",
"Ocorreu um erro inesperado, se persistir o erro, entre em contado com suporte");
result.include("categoria", "erro");
}
result.forwardTo(this).contador(paginacao.getSelecionado());
}
se puder por gentileza deixar um pouco mais claro a sua ideia, porque eu sou um pouco leigo no assunto ainda.
obrigado!
só não precisa do manager.getTransaction().rollback()… o próprio vraptor vai fazer isso.
a explicação é meio complicada… mas básicamente se deu uma exception ele marca a transação como rollback-only. Se está assim eu não posso chamar o commit() senão ele lança o RollbackException.
se vc trata a exception o vraptor vai chamar o commit() e dá o pau.
Agora eu entendi, value Lucas.
Obrigado.