Plugins oferecem um jeito simples de estender e adaptar as funções do VRaptor. Eles serão executados automaticamente depois que a aplicação web iniciar e terão acesso aos dados e funções principais do VRaptor.
Alguns plugins já estão embutidos no arquivo jar do VRaptor. O Hibernate Validator Plugin e Testing Plugin são dois exemplos mais sofisticados e mostram as possibilidades e o poder da interface do VRaptorPlugin.
Nesse tutorial escreveremos nosso próprio plugin o qual logará o número total de chamados de lógicas. Cada vez que a aplicação web chama um método de lógica o "contador" incrementa e imprime o valor.
Isso involve os passos seguintes:
Esse tutorial não é apropriado para iniciantes. Você deveria ter bons conhencimentos do VRaptor e, claro, do Java.
Para criar o nosso próprio plugin teremos que escrever uma classe que implementa a interface VRaptorPlugin.
package org.vraptor.mydvds.plugin; public class MethodHitsPlugin implements VRaptorPlugin { ... }
A interface é o contrato para qualquer VRaptor plugin. Ela somente tem um método, o init(). VRaptor chamará automaticamente init() quando a aplicação terminar de carregar os componentes.
package org.vraptor.mydvds.plugin; public class MethodHitsPlugin implements VRaptorPlugin { public void init(WebApplication application) { //... } }
O método init() recebe uma referência WebApplication como parâmetro. Ela é a entrada para os dados e funções internas do VRaptor. Você encontrará muitos managers os quais darão acesso e informações sobre componentes, lógicas, variáveis injetadas ou ejetadas e muito mais....
O tutorial não pode explicar cada detalhe sobre as funções dos managers. Verifique o Java doc e também veja o código fonte dos plugins existentes.
Usando VRaptor você escreve principalmente componentes (@Component) com lógicas de negócios. Quando a aplicação inicia, ela lê todos os seus componentes e registra-os.
A interface ComponentType representa um component. Nosso objetivo é embrulhar (wrap) todos os nossos componentes em componentes "personalizados" ou adaptados.
Um simples component wrapper deve estender a classe ComponentWrapper:
package org.vraptor.mydvds.plugin; class PluginComponentWrapper extends ComponentWrapper { public PluginComponentWrapper(ComponentType component) { super(component); }
ComponentWrapper implementa a interface ComponentType e já tem todos os métodos implementados. Nós só precisamos sobrescrever o método desejado para adapta-lo .
Para nosso objetivo vamos sobrescrever o método getLogic(). VRaptor chama esse método para receber uma determinada lógica. Nosso PluginComponentWrapper final poderia ser:
package org.vraptor.mydvds.plugin; class PluginComponentWrapper extends ComponentWrapper { @Override public LogicMethod getLogic(String key) throws LogicNotFoundException { return new PluginLogicMethodWrapper(super.getLogic(key)); } public PluginComponentWrapper(ComponentType component) { super(component); } }
O método getLogic() será chamado pelo VRaptor para receber o método do componente. Ele retorna o tipo LogicMethod que representa uma lógica de negócios dentro do componente.
Como você viu, nós também embrulhamos a lógica:
Usaremos o mesmo conceito do PluginComponentWrapper. Escreveremos um wrapper para LogicMethod que executará um código antes da lógica.
Vamos estender LogicMethodWrapper para criar o PluginLogicMethodWrapper:
package org.vraptor.mydvds.plugin; class PluginLogicMethodWrapper extends LogicMethodWrapper{ public PluginLogicMethodWrapper(LogicMethod logicMethod) { super(logicMethod); } //.... }
O LogicMethodWrapper já tem todos os métodos implementados. Somente temos que sobrescrever o método execute() da classe mãe:
package org.vraptor.mydvds.plugin; class PluginLogicMethodWrapper extends LogicMethodWrapper{ private static int numberOfMethodHits; public PluginLogicMethodWrapper(LogicMethod logicMethod) { super(logicMethod); } @Override public String execute(Object component, LogicRequest request) throws LogicException { System.out.printf("Method hits: %d ", ++numberOfMethodHits); return super.execute(component, request); } }
execute() finalmente executará a lógica e nós poderemos imprimir o contador numberOfMethodHits antes.
Depois de ter escrito os wrappers para imprimir o contador vamos finalizar o método init() da interface VRaptorPlugin.
Temos que registrar todos os nossos componentes para embrulha-los com o PluginComponentWrapper. Para registrar os componentes, o VRaptor usa um ComponentManager. Com o WebApplication podemos acessar ComponentManager e registrar os wrapped componentes do tipo PluginComponentWrapper.
Vamos escrever um laço simples:
package org.vraptor.mydvds.plugin; public class MethodHitsPlugin implements VRaptorPlugin { public void init(WebApplication application) { //get all components from component manager Set<ComponentType> components = application.getComponentManager() .getComponents(); //register the wrapped components for (ComponentType component : components) { application.getComponentManager().register( new PluginComponentWrapper(component)); } } }
Nada de complicado aqui, recebemos todos os componentes do ComponentManager e os registramos usando o PluginComponentWrapper. Observe que passamos o componente "velho" no construtor do PluginComponentWrapper.
Agora qualquer chamada de lógica passa pelo nosso componente adaptado.
Finalmente teremos que registrar o plugin no arquivo vraptor.xml:
<vraptor> ... <plugin>org.vraptor.mydvds.plugin.MethodHitsPlugin</plugin> ... </vraptor>
Para escrever um plugin temos que implementar somente a interface VRaptorPlugin, mas alguns conhecimentos sobre as funções internas do VRaptor serão necessário. O tutorial mostrou como acessar algumas delas e poderá ser alterado facilmente para criar um plugin mais útil, por exemplo, de logging, autenticação ou validação.