Plugin Tutorial

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:

  1. Implementar a interface VRaptorPlugin
  2. Escrever um wrapper para os componentes
  3. Escrever um wrapper para os métodos de lógica de negócios
  4. Registrar os componentes adaptados (wrapped)
  5. Registrar o plugin no arquivo vraptor.xml

    Esse tutorial não é apropriado para iniciantes. Você deveria ter bons conhencimentos do VRaptor e, claro, do Java.

VRaptorPlugin interface

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.

Component wrapper

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:

Logic Method Wrapper

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.

Terminando o plugin

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.

vraptor.xml

Finalmente teremos que registrar o plugin no arquivo vraptor.xml:

<vraptor>
        ...
        <plugin>org.vraptor.mydvds.plugin.MethodHitsPlugin</plugin>
        ...
</vraptor>

Conclusão

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.