[VRaptor] Exception Handling não funcionando

// add error attributes compliance with servlet spec

ou seja, pra ficar compatível com a api de servlets…

abre uma issue pra ver isso por favor:

se quiser mandar um pull request também seria muito bem vindo =)

Issue criada:

Pull request criado

Valeu pela ajuda cara!
Abraço.

vulpios, esse erro foi detectado há alguns dias atrás por mim e pelo Lucas. Tenho usado o exception handler tranquilamente com forward, porém redirect ou qualquer outro result é ignorado, estourando na tela.

Teu pull request corrige isso, porém causa um outro problema: se der um erro, eu quero capturar a exception e mostrar na outra tela fazendo um forward. No teu pull request a exception é simplesmente suprimida, então não tenho como exibir mais as mensagens na tela.

Uma sugestão do Lucas é usar outros atributos, que não o javax.servlet.error.exception, pois é ele juntamente com o javax.servlet.error.status_code que dão os erros. Experimente simplesmente comentar essas linhas que você vai notar que tudo funcionará bem.

Vamos fazer uns testes encima do pull request, e depois te aviso.

Abraço

Então Garcia,

Entendemos aqui o comportamento apesar de não concordar com ele.
Fizemos então uma implementação seguindo a ideia do Lucas que você mostrou. No Final ficou assim:

Meu controller
SistemaController

	@Post("/sistema/save")
	@Override
	public void save(Sistema sistema) {
		getResult().on(RepositoryExceptionHandler.class).forwardTo(this).saveError();
		super.save(sistema);
		addSucessMessage("Inclusão efetuada com sucesso");
		getResult().redirectTo("/sistema/novo");
	}
	
	@Public
	@Get
	public void saveError(){
		addErrorMessage("Erro ao salvar os dados para o novo Sistema");
		getResult().redirectTo("/sistema/novo");
	}

A classe que sobrescreve o ExceptionHandlerInterceptor

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.ExceptionMapper;
import br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor;

import com.google.common.base.Throwables;

/** 
 * SSOExceptionHandlerInterceptor.java
 * 
 * @author Markus Reichel ? BRQ Java Team 
 * 
 * History: 
 *    29/06/2011 - Markus Reichel
 */
@Intercepts
public class SSOExceptionHandlerInterceptor extends ExceptionHandlerInterceptor{

    private final Result result;
    private final HttpServletRequest request;

    protected static final Logger logger = LoggerFactory.getLogger(SSOExceptionHandlerInterceptor.class);
    
	public SSOExceptionHandlerInterceptor(ExceptionMapper exceptions,
			Result result, HttpServletRequest request) {
		super(exceptions, result, request);
		this.result = result;
		this.request = request;
	}

	@Override
	protected void reportException(Exception e) {
		Throwable rootCause = Throwables.getRootCause(e);
        result.include("sso.javax.servlet.error.exception", rootCause);
        result.include("sso.javax.servlet.error.exception_type", rootCause.getClass());
        result.include("sso.javax.servlet.error.message", rootCause.getMessage());
        result.include("sso.javax.servlet.error.request_uri", request.getRequestURI());
	}
	
}

e o JSP que recebe a mensagem de erro como eu queria e se precisar a exception também

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!--
**************************************************
*                                                *
*     Project: SSO - SIGLE SIGN ON  -  v1.0.0    *
*     Author: Jorge Campos                       *
*     Date: 13/06/2012                           *
*                                                *
**************************************************
-->
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="utf-8">	
    <title id='Description'>..:: | Sabius - Unimed Fortaleza | ::..</title>
    <script type="text/javascript" src="../js/jquery-1.7.2.min.js"></script>
</head>
<body>
	<div style="font-color: green;">${responseMessageSuccess}</div>
	<div style="font-color: red;">${responseMessageError}</div>

	<!-- AQUI EU PEGO O QUE EU QUISER DA EXCEPTION -->
	<div style="font-color: red;">${requestScope['sso.javax.servlet.error.exception'].message}</div>
	
	<form name="frm" method="post" action="<c:url value="/sistema/save"/>">
		ID: <input type="text" name="sistema.id" value="${sistema.id}"/><br/>
		Sistema: <input type="text" name="sistema.nomeSistema" value="${sistema.nomeSistema}"/><br/>
		Versão: <input type="text" name="sistema.versao" value="${sistema.versao}"/><br/>
		<input type="submit" value="Salvar"/>&nbsp;
		<input id="clear" type="button" value="Limpar"/>&nbsp;
		<input id="search" type="button" value="Pesquisa"/>&nbsp;
	</form>
</body>

Uma ideia interessante seria que vocês mantivessem o comportamento normal do servlet caso nenhuma exceção fosse tratada do jeito que esta, mas caso haja o tratamento o vraptor leria configurações de um properties com essas variáveis onde deveriam setar o exception
do tipo:

javax.servlet.error.exception.equivalent=sso.javax.servlet.error.exception

ou algo parecido ou melhor do que isso aí e no método reportException verificaria a existencia desses properties

Abraço cara!
Valeu pela ajuda.

Porque você não concorda? E como você acha que deve ser?

Minha visão é de quem sempre que ocorra um erro, você deixe as informações dela em algum ponto para que você possa fazer algo como mostrar para o usuário, etc. Um exemplo é que você pode tentar incluir um usuário que já existe, então uma Exception será lançada. Como você irá mostrar a mensagem para o usuário? Com estes atributos no request, basta fazer um requestScope[‘javax.servlet.error.message’] para pegar a exception. Ou no caso de uma errorpage do JSP basta fazer e.getMessage().

Eu gostei muito da idéia do prefixo SSO nos atributos, e acho muito bom assumir algo assim então. Minha sugestão lá no pull request é de colocar então o prefixo vraptor antes do javax.xxxx, o que ficaria algo assim:

result.include("vraptor.javax.servlet.error.exception", rootCause); result.include("vraptor.javax.servlet.error.exception_type", rootCause.getClass()); result.include("vraptor.javax.servlet.error.message", rootCause.getMessage()); result.include("vraptor.javax.servlet.error.request_uri", request.getRequestURI());

Opa Garcia, minhas desculpas!

Me expressei mal! Não é com a visão que não concordo, essa é fantástica! Adorei a ideia do modo de controlar as exceções, o que não concordei foi com a execução de como ela foi feita, que é de fato o bug.

É uma Excelente ideia utilizar as variáveis com o prefixo vraptor, eu só não retiraria o comportamento normal da especificação do servlet que é como esta! Faria um meio termo entre os dois, pois se não houver tratamento, o erro 500 deve ser mandado para a tela de qualquer jeito!

Abraço.

Fazer set dos atributos javax.servlet.* é somente para quando você trata a exception. Quando você quer que exiba a tela de erro padrão do appserver, basta estourar a exception sem tratamento algum. Isso é o que acontece aqui:

if (!(e.getCause() instanceof Exception) || !replay((Exception) e.getCause())) { throw e; }

Abraço