VRAPTOR (Enum + controller = redirect problem)

13 respostas
maruero

Boa tarde senhores,

Tenho um método de um controller que espera receber como parâmetro um enum, assim:

@Get
@Path( "/payment" )
public void payment( Type type ){
     System.out.println( type );
}

Se eu faço um request no browser, da maneira a baixo, tudo ocorre normal.
http://localhost:8080/meuwar/payment?type=CARTAO

Entretanto, se eu faço um redirect de algum outro método, da maneira a baixo, o type é nulo, e se eu uso-o, naturalmente, eu obtenho um NullPointerException.

result.redirectTo( MinhaClasse.class ).payment( Type.CARTAO );

O que estou fazendo de errado?
Ou isso é um “bug” do VRaptor?

13 Respostas

joeroots

aqui funcionou perfeitamente:

public enum Type {
	CARTAO, BOLETO
}

Controller:

@Get
@Path("/pay")
public void pay(Type type){
	System.out.println(type);
}

@Path("/")
public void index(){
	result.redirectTo(this).pay(Type.CARTAO);
}

Saida:

CARTAO

________edit
para ele funcionar com o get eu fiz o seguinte:

@Get
@Path("/pay/{type}")
public void pay(Type type){
	System.out.println(type);
}

e acessei assim:

/pay/CARTAO

Saida:

CARTAO
Lucas_Cavalcanti

maruero, dá null pointer na linha do redirect, ou depois do redirect?

maruero

Depois do redirect.

Ou seja, o type na linha 04 do código a baixo está nulo.

@Get  
@Path( "/payment" )  
public void payment( Type type ){  
     System.out.println( type );  
}
Lucas_Cavalcanti

maruero, não consegui reproduzir o bug… que versão vc está usando do vraptor?

maruero

3.2.0

Estranho.

Eu coloquei um Interceptor apenas para verificar se o parâmetro está sendo passado corretamente, e no construtor do interceptor eu recebo um MethodInfo com um Type dentro.
Apenas no controller mesmo que o parâmetro fica nulo. Como se o VRaptor não soubesse interpretá-lo antes de chamar o método paymento do controller.

Vou continuar procurando possiveis erros.

Lucas_Cavalcanti

vc consegue reproduzir esse erro a partir do blank-project do vraptor?

maruero

Consegui reproduzir o erro no black_project e descobrir a fonte do problema, mas tive que fazer várias alterações.

O problema começa ocorrer quando eu implemento uma InterceptorSequence definindo nela o ParametersInstantiatorInterceptor como primeiro Interceptor a ser executado.
Preciso disso, pois tenho um outro Interceptor (responsável por disponibilizar a tela de login ao usuário quando este tenta acessar páginas de acesso restrito, e após o login dá um forward ao controller original requisitado pelo usuário) que necessita conhecer os parâmetros passados da JSP para os Controllers.

Alguem tem uma sugestão de consertar meu problema?

Lucas_Cavalcanti

entendi.

Se vc coloca o ParametersInstantiatorInterceptor num InterceptorSequence ele é registrado duas vezes. Por isso o nullPointer.

na próxima versão do VRaptor que sairá em breve, você pode fazer simplesmente:

@Intercepts(after=ParametersInstantiatorInterceptor.class)
public class SeuInterceptor ...{..}

sem necessidade do InterceptorSequence.

use por enquanto esse snapshot:
https://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.2.1-SNAPSHOT/vraptor-3.2.1-20110117.201244-10.jar

maruero

Obrigado Lucas.

Lucas_Cavalcanti

se der qqer erro nesse snapshot ou vc tiver alguma sugestão por favor me avise, pra gente corrigir antes de lançar a versão nova

maruero

Lucas,

Estou usando o snapshot e estou com um comportamente um pouco estranho.
Tenho 3 interceptors meus:

  • Login
  • Exceptions
  • Initialization

Fiz o seguinte:
Exceptions executa “after” ParametersInstantiationInterceptor
Initialization executa “after” Exceptions
Login executa “after” Initialization

A idéia era deixar a sequencia assim:
ParametersInstantiationInterceptor -> Exceptions -> Initialization -> Login -> Controllers.

A sequencia está sendo respeitada, mas, estranhamente, os Controllers são instanciados antes de ser interceptados.
Ou seja, os construtores dos controllers executam antes dos Interceptors, isso está certo?

Isso está quebrando um pouco a idéia do meu InitializationInterceptor que é recuperar os parâmetros do contexto e colocá-los na sessão, para que os construtores dos controllers possam configurar os controllers durante o processo de inicialização.

Lucas_Cavalcanti

coloca o que precisa rodar antes de instanciar o controller com before=InstantiatorInterceptor.class…

por padrão ele só é antes de executar o método, não necessariamente antes de instanciar o controller

maruero

Obrigado.
Funcionou!!!

Criado 17 de janeiro de 2011
Ultima resposta 19 de jan. de 2011
Respostas 13
Participantes 3