Controller e DAO genéricos

Fala pessoal, tudo bem?

Eu estava olhando o meu projeto e eu percebi que tenho 20 funcionalidades “idênticas” onde estou tendo mais de 60 telas… gostaria de fazer algo mais genérico…

Eu estou apanhando um pouco… Por exemplo, o meu DAO, por ser genérico, tem que receber a Classe que ele vai fazer as coisas… Existe alguma forma do VRaptor entregar para ele qual classe é? (Estava pensando em passar o nome dela por parâmetro no “/path”)

Por exemplo:

o link /tabelas/arquivo/novo iria exibir o formulario para a inserção de um novo arquivo…

meu @Path ficaria assim:

@Get("/tabelas/{funcionalidade}/novo")

Existe alguma forma de fazer isso?

o VRaptor não vai conseguir injetar a classe no seu DAO genérico do jeito que vc quer, mas vc pode criar os específicos e anotá-los com @Component.

vc pode criar um Controller genérico e os controllers específicos herdando dele, e só os específicos anotados com @Resource.

se vc fizer o @Get("/tabelas/{funcionalidade}/novo") vc que vai ter que fazer o trabalho de despachar a requisição pro lugar certo… e o VRaptor já faz isso pra vc.

Na verdade eu gostaria de ter somente 3 JSPs, 1 Controller e 1 DAO. Para todas as 20 funcionalidades…

Mas eu precisava de alguma forma de saber qual funcionalidade está sendo chamada…

E o conteúdo varia de acordo com as tabelas… Mas ai eu não posso usar a passagem de parâmetros para a JSP através do retorno do método… E sim pelo result.include…

Não acho que isso seja legal, mas enfim:

@Path("/tabelas/{funcionalidade}/novo")
public void novo(String funcionalidade) {
     //lógica bizarra pra descobrir como fazer...
}

dá pra vc receber uma Class<?>, se vc criar um converter:

@Convert(Class.class)
public class ClassConverter implements Converter<Class> { // do vraptor

   public Class convert(String value, ...) {
         //converta a string para a class da sua funcionalidade
   }

}

@Path("/tabelas/{funcionalidade}/novo")
public void novo(Class funcionalidade) {
     ...
}

se vc chamar a URI /tabelas/CadastroMagico/novo, no converter vc teria disponível a string value = “CadastroMagico”.

Have fun :wink:

Só uma curiosidade… Se eu tentar receber essa class no construtor… dá certo se eu usar o converter?

Acredito que não tem nada a ver… Mas vale a pena tentar… :smiley:

Por que eu queria poder enviar para o construtor do controller qual a funcionalidade…

A verdade é que as funcionalidades são MUITO iguais… só muda o título e a tabela aonde o hibernate vai buscar as informações…

até dá…

mas não vai ser com o converter…

crie esse componente:

@Component
public class Maroto {
    public Maroto(HttpServletRequest request) {
          this.classe = transformaEmClasse(request.getParameter("funcionalidade"));
    }

    //getClasse

    //transformaEmClasse
}

e receba esse componente no construtor do controller…

vc até pode fazer esse componente ser um ComponentFactory e receber a Class no controller, só é um pouco mais bizarro :wink:

Para eu receber essa funcionalidade pelo HttpServletRequest, eu preciso informá-la por um input hidden ou o VRaptor também entende se eu passá-la pela URL, assim:

/tabelas/{funcionalidade}/novo

se vc passar pela url tb funciona

Fiz os testes aqui e funciona tudo direitinho… mas eu estou com problemas para usar o result.redirectTo();

Pois aparentemente ele não carrega o valor da funcionalidade… É isso mesmo? Eu perco o valor que estava antes?

ele não vai perder, se vc fizer um redirect para uma lógica anotada com @Path("…/{funcionalidade}/…")

Edit: falei besteira… ele vai perder sim =/

o VRaptor preenche esses parâmetros da url com o que vc passou por parâmetro no redirectTo…

dá pra fazer isso funcionar, mas vc vai ter que sobrescrever um componente do VRaptor.

é algo parecido com isso:

só que ao invés de tenant.name seria a funcionalidade.

com esse componente vc nem precisa colocar o “/tabela/{funcionalidade}” antes de todos paths

Mas então, como que eu vou informar qual a é a funcionalidade corrente?

Eu consegui da seguinte forma:
No meu factory de Funcionalidade eu vejo se o que veio é vazio e ele devolve a última preenchida…

Funciona, mas me interessei por esse componente…

então, se vc der uma olhada no método urlFor do gist que eu te passei, ele coloca o tenantPrefix(), usando o tenant.name que está na request atual.

é só vc mudar isso pra pegar a “funcionalidade” da request atual.