[Vaptor] Controller + Generics + @Path

8 respostas
X

Pessoal,

Dúvida. Estou fazendo alguns testes de CRUDs genéricos para entidades. Baseado nisso, vamos supor que tenho um Controller abstrato que seria algo como:
public abstract class AbstractCrudController<ENTITY, KEYTYPE> {
	
        //....

	@Get
	@Path("")
	public void list(){
	}
	
	@Get
	@Path("{id}")
	public ENTITY load(KEYTYPE id){
		return repository.get(id);
	}
}
E temos o controller concreto da entidade que seria:
@Resource
@Path("/users")
public class UsersController extends AbstractCrudController<User, String> {
}
Fiz este teste, porém o Vraptor não consegue popular o meu objeto String no método load() do abstract. Obviamente, caso eu "tipe" o meu load() como String o valor é populado.

temos alguma opção para este caso?

Valeu!

8 Respostas

Lucas_Cavalcanti

o VRaptor não consegue descobrir essa que o parâmetro do método é uma string pq o java apaga o tipo genérico (erasure).

uma opção seria sobrescrever o método chamando o super, aí o método é sobrescrito com os tipos concretos e o VRaptor consegue descobrir o tipo.

não sei se é possível fazer isso automaticamente. Chega a dar algum erro ou só vem null pro método?

X

Fala Lucas!

Não  erro não. Apenas o atributo não é setado. Uma maneira que funciona é fazendo a sobrecarga do load() com os tipos possíveis e utilizar o priority do @Path:
public abstract class AbstractCrudController<ENTITY, KEYTYPE> {  

    @Get  
    @Path(priority = 1, value = "{id}")  
    public ENTITY load(Long id){  
        //...
    }  

    @Get  
    @Path(priority = 2, value = "{id}")  
    public ENTITY load(String id){  
        //...
    }  
}

Não é muito elegante, mas funciona. No meu caso, estou fazendo uma PoC com o VRaptor + GAE + Twig. Neste ponto, os @Ids do Twig são somente Longs e Strings, portanto NESTE caso não vejo muito problema.

Aguma outra idéia? rs

Valeu!

Lucas_Cavalcanti

qual versão do VRaptor vc está usando mesmo?

X

3.1.3 + vraptor-gae.jar :smiley:

Lucas_Cavalcanti

na última versão funciona, se vc fizer:

@Get    
    @Path("{entity.id}")
    public ENTITY load(ENTITY entity){    
        //...  
    }

e vc pode usar para priorities: Path.LOWEST Path.LOW, etc

X

Então…

Fiz a atualização da versão e fiz o teste da maneira como vc disse... Agora, na inicialização do projeto recebo a exception:
IllegalArgumentException: Parameters paths are invalid: [entity.id] for method public java.lang.Object br.com.poc.AbstractCrudController.load(java.lang.Object)
Outro problema neste abordagem é que desta maneira preciso garantir que todas as entidades tenham um atributo id (entity.id), o que não seria uma boa idéia...
Lucas_Cavalcanti

vc pode criar uma interface Identifiable com o getId() e fazer no controller genérico usar <ENTITY extends Identifiable, …>

X

rsss…

Foi exatamente o que eu fiz :D

para objetos que não tem um atributo id como default, nos getId e setId manipulo o atributo identificador da classe...

valeu mesmo pelo help, Lucas!

Até!

Criado 30 de março de 2011
Ultima resposta 2 de abr. de 2011
Respostas 8
Participantes 2