VRaptor 3 - tratamento de erro nas aplicações

Recentemente conversei com o Guilherme Silveira a respeito de tratamento de erros em aplicações escritas para o VRaptor.
Minha idéia era escrever um Interceptor que nao deixasse vazar nenhuma exception para o usuário, até aí muito simples, basta fazer algo +/- assim:

 public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance) {
        String message = null;
        boolean redirect = false;
        try {
            stack.next(method, resourceInstance);
        } catch (Throwable e) {
           ....
            this.result.include("error", messageAmigavel);
            this.result.use(Results.page()).forward("/jsp/error.jsp");
        }
    }

até aí sem problemas.

Agora vamos melhorar um pouco para o usuário, no lugar de jogar o cara para uma página genérica de erro eu quero “manter o cara na pagina que ele está” e adicionar uma msg de erro, eu poderia fazer algo como this.result.use(Results.page()).redirect(requset.getHeader(“Referer”)), mas nesse caso como o redirecionamento é client-side, a mensagem de erro nao mais estará dísponível, nem os outros valores que eventualmente se queira “manter”.

Depois de comentar isso com o Guilherme a resposta dele foi: “o lucas e o kung tinham uma conversa sobre isso, mas com certeza posta!”

Como vcs estão fazendo isso por aí? Alguma sugestão?

[]s
galmeida

aparentemente um this.result.use(Results.page()).forward() resolve parte do problema.

sim,…

uma outra saída é adicionar um erro de validacao:

validator.add(new ValidationMessage());
validator.validate();

daí vai pra página de erro padrão da validação…

por enquanto o validator está obrigando a especificar qual é a página de validação…
mas provavelmente a gente vá tentar redirecionar pro referer com a mensagem de validação, mesmo…

[quote=lucascs]sim,…

uma outra saída é adicionar um erro de validacao:

validator.add(new ValidationMessage());
validator.validate();

daí vai pra página de erro padrão da validação…

por enquanto o validator está obrigando a especificar qual é a página de validação…
mas provavelmente a gente vá tentar redirecionar pro referer com a mensagem de validação, mesmo…
[/quote]

Falar nisso, fiz:

this.validator.onError().goTo(MyController.class).myLogic();

e mais a frente:

this.validator.add(new ValidationMessage("erro","message"));

mas ele não me redirecionou pra MyController.myLogic, me redirecionou para o jsp padrão: /WEB-INF/jsp/my/myLogic.jsp

Preciso fazer alguma coisa a mais pra fazer isso funcionar?

[]'s

o validator executa a lógica que você pediu (execução de método java mesmo) e redireciona pra view dela…
teoricamente você estaria redirecionando pra página de formulário que você já está…

o que você queria fazer? mudar a url do browser e executar a lógica tudo de novo?

[quote=lucascs]o validator executa a lógica que você pediu (execução de método java mesmo) e redireciona pra view dela…
teoricamente você estaria redirecionando pra página de formulário que você já está…

o que você queria fazer? mudar a url do browser e executar a lógica tudo de novo?[/quote]

Estou redirecionando para outra lógica, mas percebi o erro, estava faltando o validator.validate(), mas não tem nada sobre isso na doc. Adiciona lá :wink:

coloquei na documentação, obrigado =)

lucas, sera que nao era melhor dar um WARN caso um validator injetado nao tivesse seu .validate() invocado ate o final da execucao?

acho uma ótima idéia

Hoje recebi uma mensagem privada a respeito desse tópico, e para enriquecer a discussão e contar com a ajuda dos mais experientes no vraptor estou trazendo a discussão p/ cá

[quote=monike]OIe, boa tarde!

Vi uma dúvida no forum e tb gostaria que pudesse me explicar como fez.É a primeira vez que uso VRAPTOR.
Como faço para validar caso ocorra o erro?
Eu to usando hibernate…como mostrar na página “atual” pro usuário o erro , como direcionar o erro para esta página?
Tenho que mexer no meu validateAdd, no meu metodo void add, criar um interceptor
Se vc tiver um exemplo ai te agradeceria muito!!!

obrigada,

Monike.
[/quote]

Olá Monike,

se o seu problema for a validação aí vão algumas informações útis p/ vc:

  • no site do vraptor tem a documentação de como fazer validação: http://vraptor.caelum.com.br/documentacao/validacao/
  • aparentemente vc precisa chamar [color=darkblue]validator.validate()[/color] para iniciar a validação, a documentação não menciona isso ([color=darkred]isso está certo?[/color])
  • usando os validators o método documentado para definir a página que será exibida quando houver erro de validação é: [color=darkblue]validator.onError().goTo(SeuController.class).metodo()[/color] (ver na documentação)

mas pelo que vc escreveu parece que o que vc quer fazer é “pegar” exceções dentro do controller, criar a mensagem de erro e exibi-la na página de “origem” (referer) do usuário, correto? Esse é exatamente o problema que eu tentava resolver nesse tópico. Infelizmente ainda não consegui uma solução boa, provavelmente voltarei a trabalhar nisso amanhã. (algum dos experts consegue nos ajudar?)

[]s
galmeida

Sim, está certo. Mas você usar o modo fluente não precisa chamar o [color=darkblue]validator.validate()[/color]

Se você sempre utilizar uma action/method para renderizar a pagina, então vc pode redirecionar pra tela de formulario do controller com o [color=darkblue]validator.onError().goTo(SeuController.class).metodo()[/color]

Se não me engano, uma das próximas issues é redirecionar para o referer caso dê erro de validação (lucas?)
Aproveitando a deixa, to querendo fazer um ‘forward after login’, alguém tem alguma ideia sobre isso?

Olá, criei um interceptor para o tratamento de exceções, pois foi a forma que achei melhor, fiz do seguinte modo:

public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance) throws InterceptionException { try{ stack.next(method, resourceInstance); }catch(Exception exception){ this.result.include("error", exception.getMessage()); this.result.use(Results.page()).forward(); } }

E possuo um método que lança uma exception do seguinte modo

				throw new Exception("mensagem de erro");

Porém, em vez do vraptor receber uma exceção no método itercept com a mensagem “mensagem de erro”, ele está recebendo uma mensagem “java.lang.Exception: mensagem de erro”, acho que em algum ponto ela está sendo renomeada entre o controller e o interceptor, alguém teve um problema parecido?

Obrigado.

ola nicko

voce nao esta chamando o toString da exception ou concatenando a referência com alguma string? por default, o toString de um exception mostra o noma da classe da exception seguido pelo valor do getMessage().

onde isto esta aparecendo? no jsp na hora que voce faz ${error}?

só pra registrar a todos os interessados nas validacoes: o ultimo beta do vraptor alterou o esquema de validacao.
agora o validate nao existe mais e vc chama o goTo depois de ter feito o checking (ou os add(Message)). o goTo na pratica chama o validate antigo (que agora é private)

tambem implementamos um esquema de validacao nos setters dos seus beans.
quem nao gosta de espalhar codigo de validacao no controller (eu por exemplo prefiro validar no setter do bean) pode usar isso agora q o vraptor valida.

[quote=Paulo Silveira]ola nicko

voce nao esta chamando o toString da exception ou concatenando a referência com alguma string? por default, o toString de um exception mostra o noma da classe da exception seguido pelo valor do getMessage().

onde isto esta aparecendo? no jsp na hora que voce faz ${error}?[/quote]Não estou usando o toString, estou usando como mostrei ali, dando inspect no objeto quando ele está no interceptor o valor já está lá com o “java.lang.Exception:”, no jsp mostra o “java.lang.Exception:”, porém é por que ele já está sendo mandado assim. Quando crio a exceção a mensagem está correta, quando cai no interceptor já está com o prefixo. Estou usando exatamente como mostrei, alguma idéia?

Obrigado.

oi nicko!

o inspect dos debuggers vao chamar o toString do objeto! por isso esta aparecendo aquela mensagem! se voce deixar rodar o programae e usar ${erro} no JSP, vai vir so a mensagem de erro.

lembre-se que nao é muito bom usar a classe Exception diretamente, e sim uma das suas filhas, pra sempre trabalhar com algo mais especifico.

[quote=Paulo Silveira]oi nicko!

o inspect dos debuggers vao chamar o toString do objeto! por isso esta aparecendo aquela mensagem! se voce deixar rodar o programae e usar ${erro} no JSP, vai vir so a mensagem de erro.

lembre-se que nao é muito bom usar a classe Exception diretamente, e sim uma das suas filhas, pra sempre trabalhar com algo mais especifico.[/quote]Olá, desculpe, acho que não me expressei direito, dou um inspect no “exception.getMessage()”, que é a mensagem, se desse inspect no objeto ele mostraria o nome da classe como prefixo, que não é o problema. No meu jsp tenho:

<fmt:message key="${error}"/> e ele exibe “???java.lang.Exception: mensagem de erro???”.

Esse era um teste, pretendo usar uma exception precisa para manipular os erros que espero. Novamente, muito obrigado pela ajuda.

Te certifica de sempre logar a stack trace da exception, senão a complexidade vai crescendo, dai um erro acontece e esse deu catch vai pegar tudo e engolir a stack trace…

Esses controles de erro do vraptor3 funcionam com exceptions lançadas pela minha aplicação (business exceptions por exemplo) ou apenas trata erros de validação?

Não funcionam com business exception (embora vc possa fazer uma gambiarra e usar os erros de validação como erros de aplicação, mas não é aconselhável). Eu estou implementando um handler pra business exceptions com AOP, assim que tiver pronto posto aqui e mando pra galera do vraptor dar uma olhada.

[]'s