Validation perdendo as mensagens quando usado RequestDispatcher.dispatcher

8 respostas
G

Fazendo o seguinte código, as mensagens de validação aparecem normalmente:

validator.add(new ValidationMessage("Blah blah blah", "error")); RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jspx/get-the-error.jspx"); dispatcher.forward(request, response);

Porém quando faço forward para uma outra “action” perco as mensagens:

validator.add(new ValidationMessage("Blah blah blah", "error")); RequestDispatcher dispatcher = request.getRequestDispatcher("/throws-an-error"); dispatcher.forward(request, response);

Porque esse comportamento? O validator é instanciado novamente perdendo a referencia anterior mesmo quando estou no mesmo request anterior?

8 Respostas

Lucas_Cavalcanti

Olá garcia,

primeiro de tudo, não precisa usar o request dispatcher:

result.use(page()).forward("/WEB-INF/jspx/get-the-error.jspx");

faz o que você quiser fazer… e se quiser fazer isso pra outra lógica:

result.use(logic()).forwardTo(OutroController.class).jogaOErro();

vai funcionar…
quando vc abre outra requisição para lógica usando o request dispatcher:

  • com o Pico o VRaptor cria outro container de request e reinstancia tudo que eh request-scoped…
  • com o Spring, dá pau porque o spring controla o request scope usando thread locals, e acontecem
    coisas estranhas…

se você usar o result vai funcionar direito em ambos os casos

[]'s

G

Lucas, obrigado.

G

Lucas, o problema de usar o Results.page().forward é que estou redirecionando para uma url que existe uma rota, portando o erro é lançado:

br.com.caelum.vraptor.InterceptionException: br.com.caelum.vraptor.view.ResultException: Given uri /security/user/new/ responds to method: public void xw.web.controller.security.UserController.editNew(). Use result.use(logic()).redirectTo(UserController.class).editNew() instead.

Só que nesse componente eu não sei qual a rota, ou seja, o máximo que eu tenho é o response.referer. Como eu faço então para a partir do URI saber qual a rota, para assim usar o result.use(logic())?

Lucas_Cavalcanti

Entendi o que vc quer fazer:

você pode fazer o seguinte:

  • crie a classe:
@Component
public class Referer implements View {
     public Referer(Router router, MutableRequest request, Result result) {
           // assign fields
     }

    public void forward() {
           String referer = // pega o referer a partir do request
           ResourceMethod method = router.parse(referer, HttpMethod.GET, request);
           
           //forward pro método que deu match na url do referer
           Object instance = result.use(logic()).forwardTo(method.getResource().getType());
           method.getMethod().invoke(instance);
    }
    // para fazer import estático
    public static Class<Referer> referer() {
            return Referer.class;
    }
}

daí você pode fazer algo do tipo:

validator.onErrorUse(referer()).forward();

o que você acha? vou colocar isso no código do vraptor

G

Lucas, muito bom.

Abraços

G

Lucas, fica uma observação. O referer contém o URL completo, mas você precisa do URI para buscar a rota. Então fiz isso (usando commons-lang):

String referer = request.getHeader("referer"); String host = request.getHeader("host"); String uri = StringUtils.substringAfter(referer, host);

Caso você não use o commons-lang no projeto, é simples fazer um String.substring.

Abraços

Lucas_Cavalcanti

foi implementado já, vai sair no próximo release… mas se você quiser usar já, é só baixar do github e compilar o jar…

o uso ficou:

result.use(referer()).redirect();

e caso não exista o Referer setado, vai lançar uma IllegalStateException

G

Muito obrigado :stuck_out_tongue:

Criado 8 de outubro de 2009
Ultima resposta 15 de out. de 2009
Respostas 8
Participantes 2