Salve guj, estou criando uma aplicação e não sei como resolver o problema de Exceptions em requisições AJAX.
Minha aplicação tem aquele filtro comum para o hibernate:
try {
HibernateUtil.openSession();
HibernateUtil.begin();
chain.doFilter(request, response);
HibernateUtil.commit();
}catch (Throwable e) {
HibernateUtil.rollback();
porém em uma requisição AJAX não importa se deu erro ele sempre executa o commit
Exemplo:
<h:form>
<h:commandButton action="#{user.teste}" value="Testar" >
<f:ajax execute="@form" render="@form"/>
</h:commandButton>
</h:form>
ManagedBean:
public String teste() {
int x = 1/0;
return "next";
}
na requisição acima o filtro é executado, ele da o Begin mas no final mesmo com o erro de / by Zero ele da o commit e não chega no catch do filtro.
Alguem pode me ajudar a resolver isso?
No browser aparece um alert dizendo que houve problema com a requisição, mas o que eu queria era que fizesse o rollback no filtro e depois redirecionasse para a pagina de erro configurado no web.xml.
Só pra complementar se retirar o <f:ajax ai tudo funciona direitinho.
Achei um jeito de resolver o problema, mas achei que ficou muito gambiarra demais.
eu crio um ExceptionHandler e faço o rollback e o redirecionamento para a pagina de erro por aqui. Assim o HibernateFilter só da o begin e commit e quem da o rollback é o Handler:
public class MyExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
public MyExceptionHandler(ExceptionHandler wrapped) {
this.wrapped = wrapped;
}
public javax.faces.context.ExceptionHandler getWrapped() {
return wrapped;
}
public void handle() throws FacesException {
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
Throwable t = context.getException();
FacesContext fc = FacesContext.getCurrentInstance();
Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
NavigationHandler nav = fc.getApplication().getNavigationHandler();
try {
if(t instanceof ViewExpiredException) {
nav.handleNavigation(fc, null, "/login.jsf");
fc.renderResponse();
}else {
nav.handleNavigation(fc, null, "/erros/erro.jsf");
fc.renderResponse();
HibernateUtil.rollback();
}
} finally {
i.remove();
}
}
// At this point, the queue will not contain any ViewExpiredEvents.
// Therefore, let the parent handle them.
getWrapped().handle();
}
}
e o HibernateFilter fica assim:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
HibernateUtil.openSession();
HibernateUtil.begin();
chain.doFilter(request, response);
//Agora tem que testar antes de dar o Commit pois pode ter sido feito rollback no Handler
if(HibernateUtil.getSession().getTransaction().isActive())HibernateUtil.commit();
//Não precisa mais de catch pois o erro foi tratado no handler
} finally {
HibernateUtil.closeSession();
}
}
Alguem sabe se pode ter algum problema fazendo assim?
O que eu achei muito ruim é que eu “sumo” com a Exception no Handler e não preciso mais de catch no filter, além de que dar rollback no handler ficou muito estranho.
Alguem sabe como melhorar isso? Alguem tem alguma outra solução?
Eu ja pesquisei bastante e não consigo achar nada a respeito.
Valeu