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.