Alguém sabe se é possível de dentro de um Controller ter acesso ao BeanFactory do Spring?
Preciso fazer um factory.getBean(Classe.class)… E não posso injetar pelo construtor ou anotação pq é em tempo de execução que vou saber qual o bean que preciso.
O VRaptor tem uma interface para isso: a Container, que vc pode receber no construtor e chamar assim:
container.instanceFor(Classe.class);
De qualquer forma é meio estranho precisar desse tipo de coisa num controller, geralmente indica um problema de design da sua classe. Se você explicar o que está tentando fazer talvez a gente possa chegar numa solução melhor.
De fato é meio estranho isso que eu preciso…
E eu ja to testando outra forma para não precisar recuperar o bean desta forma.
Acontece que to arquitetando meu sistema para permitir qualquer programador desenvolva módulos pra ele… e o admin instale/remove estes módulos com o sistema em execução
Estes módulos são telas Velocity seguindo um protocolo bem simples.
Mas as vezes este módulo precisa acessar componentes internos do sistema (ex: o cadastro de usuarios). E também pode conter componentes que serão disponibilizados por outros módulos.
Só que pra ter um controle sobre os componentes do sistema o programador ao empacotar o módulo precisa incluir um XML descritor mencionando quais os componentes de sistema que o módulo precisa.
Assim, quando o sistema for executar o módulo, ele dará acesso apenas às interfaces dos componentes que estão no descritor do módulo.
Ou seja, o meu vraptor controller que carrega e dispacha o request para um novo módulo, só vai saber quais as dependências necessárias apenas quando o usuário acessar o tal módulo.
E o descritor que menciona os componentes ta sendo necessário para:
na instalação do módulo, o admin saber que tipo de informação o módulo vai poder acessar;
para o sistema saber quais componentes do sistema (aqui vou usar a BeanFactory) vai carregar quando for fazer o dispach para a página Velocity do módulo;
e para “nomear” o componente para ser acessado pelo Velocity.
O módulo nunca vai ter acesso as implemetações dos componetes, ele sabe qual interface precisa, que o sistema faz um “getBean()” pra ele se o módulo tiver permissão naquele componente (Bean do Spring)
um problema com essa abordagem é que a pessoa precisa executar lógicas de negócio dentro dos templates Velocity.
Isso é uma má pratica, vc deveria executar apenas lógica de apresentação dentro do Velocity.
com o VRaptor vc pode fazer esses módulos serem jars que contém controllers (que conseguem receber as suas dependências no construtor) e as páginas em velocity (ou jsp) para serem colocadas na /WEB-INF/vm (ou /WEB-INF/jsp).
Tem um jeito no VRaptor pra ler esses jars automaticamente e registrar tudo que tem neles.
ou vc cria um context-param no web.xml chamado
br.com.caelum.vraptor.packages com o valor do pacote base do módulo, ou vc cria um um arquivo dentro do /META-INF do jar chamado br.com.caelum.vraptor.packages com o pacote base do módulo.
Olá! Boa noite!
Po, cara… fiquei meio grilado agora.
eu também fiz algo parecido numa funcionalidade hoje, mas, já que vc falou que isso é estranho num controller, gostaria de saber sua opinião.
não sei se fui eu que entendi errado e essa situação é diferente da minha.
mas no meu caso, eu tenho 3 links de relatório que mandam para um mesmo controller.
esses links chamam o mesmo método pq o que eles fazem são a mesma coisa, mas de maneiras diferentes.
então ao invés de eu enfiar ifs dentro do dito cujo, eu criei classes Actions para cada um desses links,
implementei uma interface para todos e no controller, eu faço um class forname e dou um execute.
então fica mais ou menos assim
os links:
endereco/Action1
endereco/Action2
endereco/Action3
levando em conta que as 3 implementam uma interface x, eu faço no controle mais ou menos isso:
X x = (X)Class.forName(parametro).getInstance();
x.execute();
Essa não seria a melhor saída pra evitar os ifs, no meu caso?
Aproveitando o tópico, já que tenho a mesmíssima dúvida, sabe me dizer se eu posso fazer algo parecido no spring pra usar a bean factory?
pq eu estou na mesma situação que o nosso amigo.
Como eu dou um getInstance(), eu não consigo injetar uma dependência nessas Actions.
se é uma interface vc pode tentar fazer algo assim:
public void metodoDoController(Action action) {
action.execute();
}
passar na requisiçao um parametro
action=ClasseDaAction
e criar um converter pra ela:
@Convert(Action.class)
public class ActionConverter implements Converter<Action> {
public ActionConverter(List<Action> actions) {
this.actions = actions;
}
public Action convert(String value, ....) {
//retorna a action da classe do value, que é o parametro que vai vir da requisiçao
}
}
Então, cara…
Não consegui aplicar não.
Talvez eu não tenha deixado claro, mas estou usando o Spring MVC.
Estou falando isso pq pediu pra adicionar dependência pra @Convert, então imaginei que fosse do VRaptor, já que o tópico é para ele. lol
Só aproveitei o tópico pq achei interessante vc falar que fica estranho uma parada que eu tinha feito e tinha achado linda! hahaha
De qq forma, é a mesma situação, com frameworks diferentes. não cometi nenhum pecado, né?
Então…
Deixa eu repetir o post anterior, mas colando uns trechos.
no jsp, eu tenho 3 links
href=“blablabla/NomeAction1”
href=“blablabla/NomeAction2”
href=“blablabla/NomeAction3”
todas essas Actions implementam uma classe abstrata InterfaceAction
[code]@Component
public abstract class RelatorioActionInterface {
@Inject
protected PeriodoUtil pu;
public abstract void execute(Map<String, Object> model);
}[/code]
coloquei abstrata pq todas terão que ter esse objeto que quero injetar (e é esse que não estou conseguindo injetar!)