Introdução ao Spring Roo, Parte 3: Desenvolvimento de complementos do Spring Roo

O Spring Roo é uma ferramenta RAD que permite criar aplicativos (principalmente da Web) de forma rápida e fácil. Em seu âmago, o Spring Roo é baseado na arquitetura de complementos OSGI, o que torna fácil estender o Spring Roo adicionando complementos. O Spring Roo fornece comandos para criar complementos que possam ser facilmente disponibilizados para a comunidade de usuários do Spring Roo. Neste artigo, primeiro discutimos sobre a arquitetura do Spring Roo, falando sobre como o Spring aproveita sua própria arquitetura de complementos para fornecer diferentes recursos e, a seguir, criaremos complementos usando o shell Roo e os modificaremos para atender a nossas necessidades.

Shekhar Gulati, Senior Consultant, Xebia

Shekhar Gulati é consultor de Java que trabalha na Xebia Índia. Ele tem seis anos de experiência corporativa em Java. Ele tem extensa experiência em projetos do portfólio Spring, como Spring, Spring-WS, Spring Roo etc. Seus interesses são Spring, bancos de dados NoSQL, Hadoop, estruturas RAD como Spring Roo, computação em nuvem (principalmente serviços PaaS, como Google App Engine, CloudFoundry, OpenShift), Hadoop. Ele escreve constantemente para JavaLobby, Developer.com, IBM developerWorks e seu próprio blog em http://whyjava.wordpress.com/. Você pode segui-lo no Twitter @ http://twitter.com/#!/shekhargulati.



31/Ago/2011

Introdução

Na Parte 1 e na Parte 2 desta série "Introdução ao Spring Roo", criaremos um aplicativo corporativo completo do zero usando Spring Roo. Os primeiros dois artigos tinham como foco a criação de aplicativos da Web usando o ambiente de desenvolvimento rápido de aplicativos do Spring Roo. Abordamos vários recursos, como JPA, teste de Selenium, Spring Security, integração com e-mail, recursos sociais do Spring Roo, engenharia reversa de banco de dados etc. Agora, abordaremos a arquitetura de complementos do Spring Roo. A seguir, escreveremos complementos do Spring Roo usando addon create. Ao final deste artigo, você será capaz de criar seus próprios aplicativos para o Spring Roo rápida e facilmente.


Arquitetura de complementos do Spring Roo

Em sua forma mais simples, um complemento é um componente de software que adiciona uma capacidade especial a um aplicativo de software. Por exemplo, na maioria dos navegadores da Web, o suporte a vídeo é fornecido por complementos. Outro exemplo é o Eclipse (um IDE de software livre que muitos desenvolvedores do Java™ usam ou pelo menos conhecem). A maioria das capacidades são fornecidas por complementos, como suporte a JUnit, suporte a SVN etc. Estou usando complemento como um termo geral para plugins e extensões.

A Spring Roo também tem a noção de complementos:

  1. Para permitir que desenvolvedores terceiros criem capacidades que estendam os recursos do Spring Roo
  2. Para ajudar o Spring Roo a adicionar facilmente novos recursos
  3. Para ajudar o Spring Roo a permanecer um pequeno gênio (ou seja, reduzir o tamanho do Spring Roo)

Componentes lógicos do Spring Roo

O Spring Roo é dividida em duas partes lógicas.

Componentes principais do Spring Roo: Para permitir o desenvolvimento de complementos, o Spring Roo fornece um conjunto de componentes principais que formam um ambiente de execução hospedado para diferentes complementos. Esses componentes são Classpath, que suporta o Process Manager e o Shell. Por sua vez, o Process Manager suporta o Project e File Undo. O Project suporta Model, Metadata e File Monitor. Finalmente, há o componente Support, que é usado por todos. A Figura 1 oferece uma representação visual desses relacionamentos.

Figura 1. Componentes principais do Spring Roo
Componentes principais do Spring Roo

Vamos falar sobre alguns dos módulos principais:

  • Support— O módulo org.springframework.roo.support fornece classes do utilitário comuns usadas por todos os módulos principais e componentes. Algumas classes do utilitário incluem Assert, FileCopyUtils, XmlUtils, StringUtils, FileUtils etc. Por exemplo, se você quiser copiar o conteúdo de um arquivo para outro arquivo, poderá usar FileCopyUtils para fazê-lo por você.
  • Metadata— O módulo org.springframework.roo.metadata fornece uma interface e implementação de provedor de serviços de metadados e que inclui registro e armazenamento em cache de dependência.
  • File monitor— O módulo org.springframework.roo.file.monitor publica eventos após alterações detectadas no sistema de arquivos (a implementação padrão usa pesquisa de disco com dimensionamento automático).
  • File undo— O módulo org.springframework.roo.file.undo fornece uma facilidade de desfazer para arquivos a ser usada pelo gerenciador de processo.
  • Project— O módulo org.springframework.roo.project abstrai sistemas de criação de projetos comuns de usuário final, como Apache Maven e Apache Ant.
  • Process manager— O módulo org.springframework.roo.process.manager oferece uma abstração de sistema de arquivos do tipo ACID que inclui retrocesso de disco e sincronização de processos.
  • Classpath— O módulo org.springframework.roo.classpath executa análise de árvore de sintaxe abstrata e ligação de tipos de unidades de compilação Java e AspectJ.

Componentes principais do Spring Roo: A Spring fornece toda a funcionalidade por meio de complementos. Complementos de base que acompanham a Roo V1.1.3:

  • Add-On Creator— O complemento org.springframework.roo.addon.creator permite a criação fácil de complementos de terceiros para a Roo.
  • Backup— O complemento org.springframework.roo.addon.backup permite que backups sejam realizados para um arquivo ZIP ao digitar backup.
  • Cloud Foundry— O complemento org.springframework.roo.addon.cloud.foundry fornece suporte à VMware Cloud Foundry.
  • Configurable— O complemento org.springframework.roo.addon.configurable fornece suporte para introdução à anotação @Configurable do Spring por meio de um AspectJ ITD.
  • Database reverse engineering— O complemento org.springframework.roo.addon.dbre fornece suporte para a engenharia reversa incremental de bancos de dados existentes.
  • Data on Demand— O complemento org.springframework.roo.addon.dod fornece suporte para a criação automática de dados de amostra usados para testes de integração.
  • Email— O complemento org.springframework.roo.addon.email fornece suporte para a integração e a configuração do suporte a e-mail do Spring no projeto de destino.
  • Entity— O complemento org.springframework.roo.addon.entity fornece suporte extensivo para manter automaticamente classes @Entity da API Java Persistence.
  • Dynamic Finder— O org.springframework.roo.addon.finder cria localizadores da linguagem de consulta JPA compatíveis com preenchimento de código independente de código.
  • Git— O complemento org.springframework.roo.addon.git fornece suporte para integração de GIT no projeto. Cada comando executado com sucesso será automaticamente confirmado em um repositório GIT local.
  • GWT— O complemento org.springframework.roo.addon.gwt fornece suporte para estrutura de UI usando o Google Web Toolkit.
  • JavaBean— O complemento org.springframework.roo.addon.javabean automaticamente mantém getters/setters do JavaBean para classes com uma anotação @RooJavaBean.
  • JDBC— O complemento org.springframework.roo.addon.jdbc encapsula o acesso compatível com OSGi para drivers JDBC entregues em diferentes pacotes (primariamente usados por outros complementos).
  • JMS— O complemento org.springframework.roo.addon.jms fornece suporte para a definição de configurações do Java Messaging System no projeto de destino.
  • JPA— O complemento org.springframework.roo.addon.jpa instala um provedor JPA especificado e configura o JDBC de acordo.
  • JSON— O complemento org.springframework.roo.addon.json adiciona métodos de serialização e desserialização relacionados à JSONJ aos POJOs.
  • Logging— O complemento org.springframework.roo.addon.logging configura Log4j, incluindo a configuração em nível de log com base em comandos.
  • Pluralization— O complemento org.springframework.roo.addon.plural fornece pluralização de substantivos (primariamente usado por outros complementos).
  • Property Editor— O complemento org.springframework.roo.addon.property.editor gerencia editores de propriedades, conforme exigido pelo Spring MVC.
  • Property File— O complemento org.springframework.roo.addon.propfiles fornece suporte para o gerenciamento de arquivos de propriedades no projeto de destino.
  • RooBot Client— O complemento org.springframework.roo.addon.roobot.client fornece suporte para o gerenciamento de complementos por meio do servidor RooBot.
  • Security— O complemento org.springframework.roo.addon.security define Spring Security, incluindo páginas de login, filtros e dependências.
  • Serializable— O complemento org.springframework.roo.addon.serializable adiciona suporte a java.io.Serializable (como manutenção de UID) para os tipos Java necessários.
  • Solr— O complemento org.springframework.roo.addon.solr fornece suporte para a configuração e a integração de recursos do Apache Solr no projeto de destino.
  • Integration Test— O complemento org.springframework.roo.addon.test produz testes de integração com JUnit para entidades do projeto.
  • ToString— O complemento org.springframework.roo.addon.tostring produz um método toString() válido para qualquer classe com a anotação do JPA @RooToString.
  • WebFlow— O complemento org.springframework.roo.addon.web.flow fornece suporte para a configuração e a integração de recursos de Spring Web Flow no projeto de destino.
  • Web MVC Controller— O complemento org.springframework.roo.addon.web.mvc.controller fornece suporte para a configuração e a integração de controladores Spring MVC no projeto de destino.
  • Web MVC Embedded— O complemento org.springframework.roo.addon.web.mvc.embedded fornece extensão para o complemento MVC, que permite a adição de recursos integrados, como mapas, vídeos etc., em páginas da Web.
  • Web MVC JSP— O complemento org.springframework.roo.addon.web.mvc.jsp configura e integra recursos do Spring MVC JSP no projeto de destino.
  • Selenium— O complemento org.springframework.roo.addon.web.selenium fornece configuração e integração de testes da Web Selenium no projeto de destino.

Agora que vimos os componentes principais e complementos base do Spring Roo, escreveremos nossos próprios complementos.


Ambiente de tempo de execução do OSGi

A Spring Roo é baseada em OSGi, que é ideal para a arquitetura de complementos da Roo. O OSGi fornece uma infraestrutura muito boa para desenvolver aplicativos orientados a serviço modulares e integrados.

O shell da Roo usa o Apache Felix como sua estrutura de tempo de execução OSGi, juntamente com o Service Component Runtime (SCR), para gerenciamento de componentes e o OSGi Bundle Repository (OBR) para resolução de pacotes configuráveis. Há vários comandos OSGi disponíveis no shell do Roo, que podem ser vistos digitando help osgi, como mostra a Listagem 1.

Listagem 1. Ajuda da Roo para OSGi
roo> help osgi 
* osgi find - Finds bundles by name 
* osgi framework command - Passes a command directly 
through to the Felix shell infrastructure 
* osgi headers - Display headers for a specific bundle 
* osgi install - Installs a bundle JAR from a given URL 
* osgi log - Displays the OSGi log information 
* osgi obr deploy - Deploys a specific OSGi Bundle Repository (OBR) bundle 
* osgi obr info - Displays information on a specific OSGi Bundle Repository (OBR) bundle 
* osgi obr list - Lists all available bundles from the 
OSGi Bundle Repository (OBR) system 
* osgi obr start - Starts a specific OSGi Bundle Repository (OBR) bundle 
* osgi obr url add - Adds a new OSGi Bundle Repository (OBR) repository file URL 
* osgi obr url list - Lists the currently-configured 
OSGi Bundle Repository (OBR) repository file URLs 
* osgi obr url refresh - Refreshes an existing 
OSGi Bundle Repository (OBR) repository file URL 
* osgi obr url remove - Removes an existing 
OSGi Bundle Repository (OBR) repository file URL 
* osgi ps - Displays OSGi bundle information 
* osgi resolve - Resolves a specific bundle ID 
* osgi scr config - Lists the current SCR configuration 
* osgi scr disable - Disables a specific SCR-defined component 
* osgi scr enable - Enables a specific SCR-defined component 
* osgi scr info - Lists information about a specific SCR-defined component 
* osgi scr list - Lists all SCR-defined components 
* osgi start - Starts a bundle JAR from a given URL 
* osgi uninstall - Uninstalls a specific bundle 
* osgi update - Updates a specific bundle 
* osgi version - Displays OSGi framework version

Comando de criação de complemento do Spring Roo

A Spring Roo vem com comandos de criação de complementos para criar vários tipos de complementos. O Add-on Creator, que expõe os comandos addon create, também é um complemento Roo. A Roo atualmente suporta quatro tipos de complementos:

  1. Complemento Internationalization — Suporta a adição de traduções de idiomas para aplicativos Spring MVC da estrutura da Roo (adição de tradução para o idioma hindi, por exemplo).
  2. Complemento Simple— Complementos simples suportam pequenas adições a dependências ou configurações de projetos, ou a ambas (fazer algumas modificações em maven pom.xml, como adicionar alguns JARs ou plug-ins Maven, por exemplo).
  3. Complemento Advanced — Este complemento faz o trabalho pesado e é usado para criar um complemento Spring Roo completo (criar um complemento que possa escrever métodos equals e hashcode para seu objeto de domínio, por exemplo). Já existe um complemento da comunidade para essas funções.
  4. Complemento Wrapper — Este complemento envolve um artefato Maven para criar um pacote configurável compatível com OSGi. Isto é preciso quando uma dependência é necessária pelo complemento para completar sua funcionalidade. Por exemplo, o complemento de engenharia reversa de banco de dados do Spring Roo requer o driver JDBC do Postgres para completar suas tarefas, então você envolverá o driver JDBC do Postgres usando este complemento.

Esses complementos criam comandos para facilitar o desenvolvimento de complementos de Roo ao criar novos complementos que são:

httppgp://

A Spring Roo V1.1 apresentou Pretty Good Privacy (PGP), permitindo que os usuários especifiquem quais desenvolvedores podiam assinar software que seria baixado e ativado no shell da Roo. De fato, cada release da Roo em si agora é assinada com PGP. Um novo manipulador de protocolos, chamado httppgp://, foi introduzido na Roo para indicar que uma URL também tem uma assinatura PGP sem blindagem disponível. Isto fornece uma forma aberta de ajudar a proteger os usuários de downloads maliciosos. Esses padrões também permitem o uso de ferramentas PHP independentes para verificar as operações da Roo

  • Integrado com o controle de código de origem do Google Code SVN.
  • Hospedado em um repositório Maven público criado como parte do projeto de código Google.
  • Compatível com RooBot, um serviço hospedado em VMware que indexa conteúdo importante em arquivos OBR públicos da Roo. O arquivo OBR é uma representação com base em XML de metadados do pacote configurável. Para serem compatíveis com RooBot, os complementos devem ser:
    1. Compatíveis com OSGi.
    2. Artefatos assinados com PGP com chaves públicas.
    3. Registrados por meio do protocolo httppgp://.

Usando o comando da Roo addon create, você obtém todos os recursos mencionados acima, automaticamente configurados para seus complementos. Isto certamente reduz o tempo para criar e publicar os complementos para o mundo exterior.

Antes de começarmos a escrever complementos, assegure-se de ter um ambiente Spring Roo funcional. Instruções para instalar o Spring Roo pode ser encontradas na Parte 1 desta série.


Desejo suporte ao idioma hindi (criação de complemento i18N)

Ao criar um aplicativo da Web com base em Spring MVC usando Spring Roo, é possível adicionar suporte a diferentes idiomas usando a linguagem Web mvc. Por padrão, a Spring Roo suporta inglês, alemão, espanhol, italiano, holandês e sueco. O suporte à internacionalização é fornecido pelo complemento Web MVC JSP, que é ativado somente depois que você tiver os arquivos JSPX em seu diretório webapp. Os arquivos JSPX são gerados por um comando do controlador que converte um aplicativo simples com base em JAR em um aplicativo da Web Spring MVC.

Sendo indiano, quero adicionar suporte para hindi em meu aplicativo da Web. A Spring Roo fornece um comando addon create i18n, que fornece uma extensão para o comando web mvc install language , adicionando suporte para um novo idioma, como hindi. A única coisa que ele requer é a tradução do arquivo messages.properties no idioma desejado.

Quando o Spring Roo cria um aplicativo da Web Spring MVC, ele cria dois arquivos de propriedades: application.properties e messages.properties. O arquivo application.properties contém as propriedades específicas do aplicativo, como o nome do aplicativo. O arquivo messages.properties contém as propriedades, que não são específicas de nenhum aplicativo, como a mensagem "Tem certeza de que deseja excluir este item?" ao clicar no botão de exclusão, ou mensagens como login, logout etc. Portanto, ao escrever um complemento i18n, é preciso fornecer a tradução do arquivo messages.properties.

Agora que já falamos sobre o suporte padrão Pa internacionalização no Spring Roo, escreveremos um complemento i18n que pode adicionar suporte ao idioma hindi. Mostrarei como é possível configurar um projeto em código Google, escrever um complemento usando o comando, publicá-lo e lançá-lo para o mundo e, finalmente, registrá-lo no serviço RooBot. O registro no serviço RooBot é importante porque permitirá que o RooBot indexe seu complemento e exiba-o quando outros desenvolvedores fizerem pesquisas usando o comando addon search.

Configuração do projeto

A documentação do Spring Roo explica de forma eloquente a configuração de seu projeto e do repositório Maven no código Google, portanto não vou repeti-la.. A única observação que farei é sobre o nome do projeto, "roo-hind-addon."

Criar um complemento i18N

Depois de configurar o projeto, você terá um diretório vazio chamado roo-hindi-addon. Acesse aquele diretório e digite roo command. Quando estiver no shell, digite addon create i18n. Se você pressionar a tecla tab, verá que este comando recebe sete atributos. Desses sete, três atributos são obrigatórios: topLevelPackage (pacote de nível superior do novo complemento), locale (abreviações de local, como "it" para italiano) e messageBundle (caminho completo para message_xx.properties, onde xx é o nome da localidade). Os outros quatro são atributos opcionais: language (nome completo do idioma), flagGraphic (caminho completo para o arquivo xx.png, onde xx é o nome do sinalizador), description (descrição do complemento) e projectName (nome do projeto; se ele não for fornecido, o nome do pacote de nível superior é usado). E u sugeriria o uso do atributoprojectName, assegurando-se de que seu valor seja o nome do projeto hospedado no código Google. Portanto, em nosso caso, ele será roo-hindi-addon.

De todos os atributos mencionados acima, o mais importante é messageBundle, que especifica o arquivo messages.properties traduzido. Para traduzir messages.properties para o idioma hindi, a opção mais fácil é usar um serviço como Google translate, convertendo cada propriedade, uma de cada vez, e, a seguir, gravando-a no arquivo messages_hi.properties. No entanto, isto não funciona em nossa situação, pois os arquivos de propriedades do Java usam a codificação ISO-8859-1, que não suporta caracteres hindi. Para solucionar este problema, usei um plugin do Eclipse chamado Eclipse ResourceBundle Editor, que permite converter e criar pacotes configuráveis de recursos para diferentes idiomas. É possível instalá-lo usando o site de atualização http://www.nightlabs.de/updatesites/development/. A conversão do arquivo messages.properties para o arquivo messages_hi.properties não pertence ao escopo deste artigo. O plugin ResourceBundle Editor é fácil de usar. Observe que, se os caracteres do idioma fossem suportados, não seria necessário usar o ResourceBundle Editor. O arquivo messages_hi.properties se parecerá com o que é mostrado na Listagem 2.

Listagem 2. Amostra do arquivo messages_hi.properties
button_cancel = \u0930\u0926\u094D\u0926 
button_end = \u0905\u0902\u0924
button_find = \u0916\u094B\u091C\u0947\u0902
button_home = \u0918\u0930 
...

Consulte o arquivo completo. Depois de traduzir o arquivo messages_hi.properties, você estará pronto para criar o complemento digitando um único comando. É possível criar o complemento do hindi digitando o comando da Listagem 3 no shell da Roo.

Listagem 3. Comando para criar o complemento do hindi
addon create i18n --locale hi --topLevelPackage org.xebia.roo.addon.i18n.hindi 
  --messageBundle <location to messages_hi.properties> \
--language hindi --projectName roo-hindi-addon 
  --flagGraphic <full path to flag hi.png>

A Listagem 4 mostra os artefatos criados pelo comando addon create i18n.

Listagem 4. Artefatos criados
Created ROOT/pom.xml 
Created ROOT/readme.txt 
Created ROOT/legal 
Created ROOT/legal/LICENSE.TXT 
Created SRC_MAIN_JAVA 
Created SRC_MAIN_RESOURCES 
Created SRC_TEST_JAVA 
Created SRC_TEST_RESOURCES 
Created SRC_MAIN_WEBAPP 
Created SRC_MAIN_RESOURCES/META-INF/spring 
Created ROOT/src/main/assembly 
Created ROOT/src/main/assembly/assembly.xml 
Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi 
Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi/messages_hi.properties 
Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi/hi.png 
Created SRC_MAIN_JAVA/org/xebia/roo/addon/i18n/hindi 
Created SRC_MAIN_JAVA/org/xebia/roo/addon/i18n/hindi/HindiLanguage.java

O comando gerou um projeto Maven que pode ser importado para o Eclipse (com m2eclipse) ou para o SpringSource Tool Suite via File > Import > Maven > Existing Maven projects. Não é preciso importar este projeto, pois não precisamos modificar o complemento.

Agora podemos instalar este complemento, usá-lo em nossos projetos e publicá-lo para o mundo externo. Mas, primeiro, vamos falar sobre alguns dos artefatos para entender melhor o código gerado:

  • pom.xml — Este é a configuração de um projeto Maven padrão. O pom.xml gerado tem vários plugins pré-configurados, que fazem o trabalho relacionado a assinatura de artefatos usando o protocolo PGP, lançando o complemento usando o plugin de release Maven e criando pacotes configuráveis OSGi usando o plugin de pacote configurável Maven. Ele também adiciona dependências OSGi e Felix ao projeto, que são necessárias para que o complemento seja executado dentro do shell da Roo.
  • assembly.xml — Define as configurações usadas pelo plugin assembly Maven para empacotar o complemento.
  • messages_hi.properties — Este é o arquivo do pacote de mensagens que fornecemos ao criar o complemento, que é copiado para a pasta de recursos.
  • hi.png — Este é o arquivo PNG do sinalizador que fornecemos ao criar o complemento, que é copiado para a pasta de recursos.
  • HindiLanguage.java — Este é o único arquivo Java criado por este complemento, usado para obter as informações correspondentes ao idioma específico. Por exemplo, ele dá o nome da localidade, o arquivo de recursos de mensagem do pacote configurável etc.

Adicionar suporte a hindi a nosso aplicativo

Agora, mostrarei como é possível adicionar suporte a hindi para seu aplicativo usando o complemento que acabamos de criar:

  1. Saia do shell roo e execute o comando mvn clean install. Durante o processo de compilação, ele pedirá sua passphrase PGP.
  2. Depois que o complemento da Roo tiver sido compilado, abra a nova linha de comando e crie um diretório chamado i18n-hindi-client. Criaremos um cliente simples para nosso complemento.
  3. Acesse o diretório i18n-hindi-client e digite o comando roo.
  4. Execute os seguintes comandos no shell da Roo. Isto criará um aplicativo da Web Spring MVC simples.
    Listagem 5. Comandos Roo para criar o aplicativo da Web MVC
    project --topLevelPackage com.shekhar.roo.i18n.client \
    --projectName i18n-hindi-client  
    persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY  
    entity --class ~.domain.MyUser  
    field string --fieldName name --notNull  
    controller all --package ~.web
  5. Digite este comando e pressione a tecla tab: web mvc language --code de en es it nl sv

    Você não verá o suporte ao idioma hindi. Isto ocorre porque ainda não instalamos o complemento do hindi.

  6. Para instalar o complemento, digite:
    osgi start --url file:///<location to addon target 
       folder>/org.xebia.roo.addon.i18n.hindi-0.1.0.BUILD-SNAPSHOT.jar

    Isto deverá instalar e ativar nosso complemento do hindi do Spring Roo. É possível visualizar o status do complemento usando o comando osgi ps, que exibe as informações do pacote configurável OSGi e seu status, como mostrado abaixo:

    [ 95] [Active ] [ 1] roo-hindi-addon (0.1.0.BUILD-SNAPSHOT)
  7. Novamente, digite web mvc language –code e pressione a tecla tab. Desta vez, você verá um código para o idioma hindi. Escolha o código hi e o suporte ao idioma hindi será adicionado ao seu aplicativo.
    web mvc language –code hi
  8. Saia do shell da Roo e digite mvn tomcat:run. Você verá a bandeira da Índia no rodapé. Clique na bandeira e seu aplicativo será exibido em hindi, como mostrado na Figura 2.
    Figura 2. Suporte ao idioma hindi
    Suporte ao idioma hindi

Depois de testar que o complemento está funcionando bem em seu sistema de desenvolvimento, é possível enviar o complemento para o projeto de código Google que criamos.

Em segundo plano

Agora que vimos que o complemento que criamos funciona, vamos ver como o idioma hindi foi disponibilizado para o aplicativo:

  1. O roo-hindi-addon será iniciado usando o comando osgi start.
  2. Quando o complemento inicia, a classe HindiLanguage que foi criada pelo comando addon create i18n é registrado no i18nComponent, que é um listener de serviço OSGi para registrar e remover complementos i18n. A classe HindiLanguage é marcada com as anotações @Component e @Service, que são fornecidas pelo Apache Felix. Essas anotações garantem que os componentes e serviços sejam registrados com o shell da Roo e estejam disponíveis para uso.
  3. Quando digitamos o comando web mvc install language –code e pressionamos a tecla tab, o serviço de preenchimento da tecla tab chama a classe i18nComponent do método getSupportedLanguages(), que retorna java.util.Set de complementos de i18n. Como HindiLanguage já estava registrado com i18nComponent, ele também foi retornado.

Publicação de complementos para o mundo externo

É fácil publicar o complemento para o mundo externo porque o comando create da Roo fez a maioria das coisas por nós ao instalar todos os plugins necessários do Maven. Acesse o diretório raiz do projeto e digite os comandos da Listagem 6.

Listagem 6. Publicação do projeto da Roo
svn add pom.xml src/ legal/ readme.txt 
svn commit -m "Roo Hindi Addon first version" 
mvn release:prepare release:perform

O plugin de release do Maven pedirá a versão do release, o nome da identificação e a versão de desenvolvimento. É possível simplesmente escolher o padrão e prosseguir. Levará alguns minutos para lançar e publicar os artefatos para o projeto do código Google. A seguir, é possível visualizar os artefatos do complemento no projeto do código Google.

Registrar seu complemento no RooBot

Depois de liberar seu plugin, poderá enviá-lo por email para s2-roobot@vmware.com para registrar o repositório de seu componente. A linha de assunto do e-mail deverá conter o arquivo repository.xml. Por exemplo, para o complemento que acabamos de criar, o repository.xml é http://code.google.com/p/roo-hindi-addon/source/browse/repo/repository.xml. Para obter mais informações sobre o registro no RooBot, consulte a documentação do Spring Roo.


Quero monitorar meu aplicativo Java (criação de complemento simples)

É um requisito comum em muitos aplicativos corporativos que você deseje monitorar seu aplicativo Java para determinar gargalos de desempenho do aplicativo. Eu também tive o mesmo requisito, portanto decidi verificar algumas soluções de software livre disponíveis. O Java Application Monitor (JAMon) é uma API Java gratuita, de alto desempenho e thread-safe que permite monitorar facilmente aplicativos em produção.

Para adicionar suporte a JAMon em seu aplicativo da Web:

  1. É preciso adicionar jamon JAR em seu pom.xml.
  2. É preciso definir um bean JamonPerformanceMonitorInterceptor em seu arquivo de contexto do aplicativo. A amostra de definição de bean parece-se com o código na Listagem 7.
Listagem 7. JamonPerformanceMonitorInterceptor code
	<bean id="jamonPerformanceMonitorInterceptor" 
		class=\
"org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"> 
		<property name="trackAllInvocations" value="true"></property> 
		<property name="useDynamicLogger" value="true"></property> 
	</bean> 

	<bean id="autoProxyCreator" 
		class=\
"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
		<property name="interceptorNames"> 
			<list> 
				<idref bean="jamonPerformanceMonitorInterceptor" /> 
			</list> 
		</property> 
		<property name="beanNames"> 
			<list> 
				<value>speakerController</value> 
				<value>talkController</value> 
			</list> 
		</property> 
	</bean>

Esta não é uma definição simples de bean de que qualquer desenvolvedor poderá lembrar-se facilmente e achei que seria ótimo se pudesse automatizar esta configuração padrão. Portanto, decidi escrever um complemento que pudesse automatizar o processo de adicionar a dependência JAMon e conectar o bean interceptador. Como você decide se precisa de um complemento simples ou avançado?

  1. Use um complemento simples quando quiser adicionar dependências do Maven, adicionar artefatos de configuração ou adicionar ambos em seu projeto.
  2. Use um complemento avançado quando precisar escrever complementos completos que aprimorem tipos Java existentes, introduzir novos tipos Java e AspectJ ITDs, ou fazer ambos em seu projeto.

Nosso requisito é adicionar jamon.jar ao caminho de classe e escrever um arquivo de contexto de aplicativo que conterá a definição de nosso bean. É melhor escrever um novo arquivo de contexto de aplicativo Spring em vez de usar arquivos de contexto existentes, pois ele ajuda a modularizar contextos de aplicativos. A partir desses requisitos, está claro que devemos escrever um complemento simples que possa adicionar suporte a JAMon a qualquer aplicativo da Web.

Configuração do projeto

Precisamos fazer a configuração do projeto da mesma forma que fizemos para o complemento de internacionalização. Chamarei este projeto de "spring-roo-addon-jamon".

Criar um complemento simples

Depois de configurar o projeto, você terá um diretório chamado spring-roo-addon-jamon somente com a pasta .svn. Acesse o diretório spring-roo-addon-jamon e inicie o shell do Spring Roo. A seguir, digite o seguinte comando:

addon create simple --topLevelPackage org.xebia.roo.addon.jamon \
--projectName spring-roo-addon-jamon

Pronto! O complemento está criado.

Instalar o complemento gerado

É possível instalar o complemento usando este comando:

osgi start --url file://<Location to addon
    target folder>/org.xebia.roo.addon.jamon-0.1.0.BUILD-SNAPSHOT.jar

Depois de instalar o complemento, crie um cliente simples, como criamos para o complemento i18n para testar. O complemento gerado fornece dois comandos:

  1. say hello, um comando que imprime uma mensagem de boas-vindas no shell da Roo. Este comando estará sempre disponível e é possível digitá-lo a qualquer momento, enquanto o shell da Roo estiver em execução.
  2. web mvc install tags substitui as tags padrão do MVC geradas ao criar a estrutura de um aplicativo da Web. Este comando estará disponível somente depois de criar um aplicativo da Web.

Verificação do código gerado

Agora que você testou o complemento, vejamos os arquivos gerados por este complemento, mostrado na Listagem 8.

Listagem 8. Arquivos gerados para spring-roo-addon-jamon
Created ROOT/pom.xml 
Created ROOT/readme.txt 
Created ROOT/legal 
Created ROOT/legal/LICENSE.TXT 
Created SRC_MAIN_JAVA 
Created SRC_MAIN_RESOURCES 
Created SRC_TEST_JAVA 
Created SRC_TEST_RESOURCES 
Created SRC_MAIN_WEBAPP 
Created SRC_MAIN_RESOURCES/META-INF/spring 
Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon 
Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonCommands.java 
Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonOperations.java 
Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonOperationsImpl.java 
Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonPropertyName.java 
Created ROOT/src/main/assembly 
Created ROOT/src/main/assembly/assembly.xml 
Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon 
Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon/info.tagx 
Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon/show.tagx

Os artefatos pom.xml, assembly.xml, LICENSE.TXT e readme.txt são os mesmos gerados pelo complemento i18n. Nós os discutimos acima e não falarei sobre eles novamente aqui. Os artefatos de maior interesse são JamonCommands, JamonOperations, JamonOperationsImpl e JamonPropertyName. Falaremos sobre cada um deles para obter um entendimento do código gerado pelo comando do complemento simples.

  1. JamonCommands.java:JamonCommands— Esta é uma classe que implementa uma interface de marcador chamada CommandMarker e expõe dois comandos, say hello e web mvc install tags, como mostrado na Listagem 9.
    Listagem 9. Código gerado por JamonCommands.java:JamonCommands
    @Component 
    @Service 
    public class JamonCommands implements CommandMarker { 
            
           @Reference private JamonOperations operations; 
            
           @Reference private StaticFieldConverter staticFieldConverter; 
    
    
           protected void activate(ComponentContext context) { 
               staticFieldConverter.add(JamonPropertyName.class); 
               } 
    
    
           protected void deactivate(ComponentContext context) { 
                   staticFieldConverter.remove(JamonPropertyName.class); 
           } 
            
           @CliAvailabilityIndicator("say hello") 
           public boolean isSayHelloAvailable() { 
                   return true; 
           } 
            
           @CliCommand(value = "say hello", 
    help = "Prints welcome message to the Roo shell") 
           public void sayHello( 
                   @CliOption(key = "name", mandatory = true, 
    help = "State your name") String name, 
                   @CliOption(key = "contryOfOrigin", mandatory = false, 
           help = "Country of origin") JamonPropertyName country) { 
                    
                   log.info("Welcome " + name + "!"); 
                   log.warning("Country of origin: " + (country == null ? \
    JamonPropertyName.NOT_SPECIFIED.getPropertyName() : country.getPropertyName())); 
                   
                   log.severe("It seems you are a running JDK " 
    + operations.getProperty("java.version")); 
                   log.info("You can use the default JDK logger anywhere in your" 
    + " add-on to send messages to the Roo shell"); 
           } 
            
           @CliAvailabilityIndicator("web mvc install tags") 
           public boolean isInstallTagsCommandAvailable() { 
                   return operations.isInstallTagsCommandAvailable(); 
           } 
            
           @CliCommand(value = "web mvc install tags", 
    help="Replace default Roo MVC tags used for scaffolding") 
           public void installTags() { 
                   operations.installTags(); 
           } 
    }

    Removi todos os comentários gerados pelo gerador de código para reduzir o nível de detalhamento do código. Vejamos os membros importantes desta classe:

    1. CommandMarker— Todas as classes de comando deverão implementar a interface CommandMarker e deverão ser anotadas com anotações @Component e @Service para que sejam registradas e seus comandos tornem-se disponíveis no shell da Roo. Os campos anotados com @Reference que são dependências da classe JamonCommands são injetados pelo contêiner OSGi subjacente da Roo. Todas as classes anotadas com anotações @Component e @Service podem ser injetadas em outros complementos.
    2. Métodos Activate e Deactivate — Os métodos activate e deactivate são os métodos chamados ao instalar o complemento usando o comando addon install ou removê-lo usando o comando addon remove . Esses métodos permitem interferir no ciclo de vida do complemento, que é gerenciado pelo contêiner OSGi da Roo subjacente.
    3. Métodos anotados com @CliAvailabilityIndicator— Os métodos anotados com @CliAvailabilityIndicator são os métodos que ajudam a ocultar comandos quando eles não estão disponíveis. Por exemplo, o comando security setup , que instala Spring Security no projeto, não está visível até que o projeto seja um aplicativo da Web. Não é necessário ter tais métodos, mas eles são úteis, pois não permitem que o usuário emita comandos que não fazem sentido naquele momento. Por exemplo, executar o comando security setup antes que o usuário tenha um aplicativo da Web não faz o menor sentido.
    4. Métodos anotados com @CliCommand— Os métodos anotados com @CliCommand registra o comando no shell da Roo. A anotação @CliCommand tem dois atributos: value, que define o nome do comando, e help, que define a mensagem de ajuda exibida ao digitar o comando help. Cada comando pode definir atributos obrigatórios e não obrigatórios usando a anotação @CliOption, apresentada como parte do comando. Por exemplo, o comando say hello tem um atributo obrigatório chamado name e um atributo não obrigatório chamado country.
  2. JamonOperationsImpl.java— Classes de comandos precisam executar algumas operações quando um comando é executado. Essas operações são realizadas por classes de operações. JamonOperationsImpl é uma classe de operações responsável por executar o trabalho de fato, como adicionar uma dependência no pom.xml ou copiar recursos para o local desejado. A classe JamonOperationsImpl executa suas operações usando serviços principais fornecidos pela estrutura do Spring Roo. Por exemplo, para adicionar uma dependência, ela usa a interface ProjectOperations . Para copiar os arquivos, usa a interface FileManager . Vejamos o código para a classe JamonOperationsImpl (veja a Listagem 10) para entender melhor o complemento da Roo.
    Listagem 10. JamonOpertionsImpl
    	@Component 
    	@Service 
    	public class JamonOperationsImpl implements JamonOperations { 
    		private static final char SEPARATOR = File.separatorChar; 
    	 
    		@Reference private FileManager fileManager; 
    		@Reference private ProjectOperations projectOperations; 
    
    		public boolean isInstallTagsCommandAvailable() { 
    			return projectOperations.isProjectAvailable() &&
                fileManager.exists(projectOperations.getProjectMetadata().
    			getPathResolver().getIdentifier(Path.SRC_MAIN_WEBAPP,
                    "WEB-INF" + SEPARATOR + "tags")); 
    	} 
    
    		public String getProperty(String propertyName) { 
    			Assert.hasText(propertyName, "Property name required"); 
    			return System.getProperty(propertyName); 
    		} 
    
    		public void installTags() { 
    			PathResolver pathResolver =
                projectOperations.getProjectMetadata().getPathResolver(); 
    			createOrReplaceFile(pathResolver.getIdentifier(
    			    Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR +
                        "tags" + SEPARATOR + "util"), "info.tagx"); 
    
    		createOrReplaceFile(pathResolver.getIdentifier(
    			Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR +
                    "tags" + SEPARATOR + "form"), "show.tagx"); 
    		} 
    	 
    		private void createOrReplaceFile(String path, String fileName) { 
    			String targetFile = path + SEPARATOR + fileName; 
    			MutableFile mutableFile = fileManager.exists(targetFile) ?
                    fileManager.updateFile(targetFile) :
                    fileManager.createFile(targetFile); 
    			    try { 
    			    	FileCopyUtils.copy(TemplateUtils.getTemplate(getClass(),
                            fileName), mutableFile.getOutputStream()); 
    			    } catch (IOException e) { 
    				throw new IllegalStateException(e); 
    			} 
    		} 
    	}

    A classe JamonOperationsImpl tem dois métodos importantes: isInstallTagsCommandAvailable verifica se o comando está disponível e installTags instala as tags no projeto de destino. Para executar essas operações, a classe JamonOperationsImpl usa alguns serviços e utilitários principais da Spring Roo:

    1. A classe ProjectOperations : JamonOperationsImpl usa o serviço ProjectOperations para verificar se o projeto está disponível e obter o caminho da pasta de tags.
    2. A classe FileManager : JamonOperationsImpl usa o serviçoFileManager para verificar se um arquivo existe em certo caminho e obter a atualização ou criar um MutableFile. MutableFile é outra classe específica da Roo que representa um manipulador para um arquivo que pode ser modificado.
    3. A classe de utilitário TemplateUtils : TemplateUtils é usada para adquirir um InputStream para arquivos de modelo (info.tagx e show.tagx) em nosso pacote configurável do complemento.
    4. A classe de utilitário FileCopyUtils : FileCopyUtils é usada para copiar os modelos (de TemplateUtils) para MutableFile (do FileManager).

Modificar um complemento para atender a nossos requisitos

Na primeira seção sobre um complemento simples, discutimos dois requisitos que devem ser atendidos para que o complemento possa configurar JAMon em qualquer aplicativo da Web Spring MVC. Os requisitos eram:

  1. Adicionar JAMon JAR em seu pom.xml
  2. Definir um bean JamonPerformanceMonitorInterceptor no arquivo de contexto do aplicativo

Para atender a esses requisitos, faremos alterações na classe JamonCommands para suportar o comando jamon setup. A seguir, adicionaremos uma operação correspondente ao comando jamon setup para fazer o trabalho real para atender aos requisitos.

JamonCommands— A classe JamonCommands agora terá somente dois métodos: isInstallJamon para verificar se o comando jamon setup está disponível e installJamon para instalar JAMon quando o comando jamon setup é emitido. (Veja a Listagem 11.)

Listagem 11. Código para JamonCommands
@Component 
@Service 
public class JamonCommands implements CommandMarker { 
	 
	private Logger log = Logger.getLogger(getClass().getName()); 

	@Reference private JamonOperations operations; 
	 
	@CliAvailabilityIndicator("jamon setup") 
	public boolean isInstallJamon() { 
		return operations.isInstallJamonAvailable(); 
	} 
	 
	@CliCommand(value = "jamon setup", help = "Setup Jamon into your project") 
	public void installJamon() { 
		operations.installJamon(); 
	} 
}

Isto é tudo de que precisamos em JamonCommands . Ele só precisa expor o comando jamon setup e o restante do trabalho é delegado para a classe JamonOperationsImpl . (Veja a Listagem 12.)

Listagem 12. Código para JamonOperationsImpl
JamonOperationsImpl

JamonOperationsImpl precisa implementar dois métodos – \
isInstallJamonAvailable() e installJamon(). 

O método isinstallJamonAvailable() retorna uma variável booleana 
indicando se o comando está disponível neste local ou não. Quero ativar 
JAMon somente para os aplicativos da Web, portanto precisamos verificar 
se o projeto é um aplicativo da Web ou não. Para tanto, escreveremos o 
código como mostrado abaixo

	public boolean isInstallJamonAvailable() { 
		return projectOperations.isProjectAvailable() &&
        fileManager.exists(projectOperations.getPathResolver()
			.getIdentifier(Path.SRC_MAIN_WEBAPP, "/WEB-INF/web.xml")); 
	}

O código mostrado na Listagem 12 usa o serviço ProjectOperations para verificar se um projeto está disponível neste local e para obter o caminho do arquivo web.xml (o arquivo web.xml só existe para aplicativos da Web). O serviço FileManager é usado para verificar se o web.xml existe no local especificado por ProjectOperations.

O segundo método que precisamos implementar é installJamon(), que deverá adicionar a dependência JAMon em pom.xml e adiciona a definição do bean ao webmvc-config.xml. Antes de escrevermos código para este método, precisamos criar um arquivo XML chamado configuration.xml dentro da pasta src/main/resources/org/xebia/roo/addon/jamon. A estrutura de pastas, org/xebia/roo/addon/jamon, pe a mesma que a estrutura de pacote de seu complemento da Roo. O configuration.xml define a versão do JAMon e a dependência JAMon JAR, como mostra a Listagem 13.

Listagem 13. Conteúdo de configuration.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<configuration> 
    <jamon> 
        <properties> 
            <jamon.version>2.4</jamon.version> 
        </properties> 
        <dependencies> 
            <dependency> 
            <groupId>com.jamonapi</groupId> 
            <artifactId>jamon</artifactId> 
            <version>${jamon.version}</version> 
        </dependency> 
        </dependencies> 
    </jamon> 
</configuration>

Vamos escrever o código para adicionar dependência em pom.xml, mostrado na Listagem 14.

Listagem 14. Conteúdo de pom.xml
	public void installJamon() { 
		Element configuration = XmlUtils.getConfiguration(getClass()); 
		updatePomProperties(configuration); 
		updateDependencies(configuration); 
	} 

	private void updatePomProperties(Element configuration) { 
		List<Element> properties = \
XmlUtils.findElements("/configuration/jamon/properties/*"
		, configuration); 
		for (Element property : properties) { 
			projectOperations.addProperty(new Property(property)); 
		} 
	} 

	private void updateDependencies(Element configuration) { 

		List<Dependency> dependencies = new ArrayList<Dependency>(); 
		List<Element> jamonDependencies = XmlUtils.findElements(
			"/configuration/jamon/dependencies/dependency", configuration); 
		for (Element dependencyElement : jamonDependencies) { 
			dependencies.add(new Dependency(dependencyElement)); 
		} 
		projectOperations.addDependencies(dependencies); 
	}

Este é um mecanismo padrão para adicionar uma dependência em pom.xml e é possível encontrá-lo em uso na maioria dos complementos da Roo. O código mostrado na Listagem 14 é autoexplicativo e usa a classe de utilitário do Spring Roo, XmlUtils, para ler o conteúdo de configuration.xml e, a seguir, o serviço ProjectOperations para atualizar o arquivo pom.xml.

Depois de adicionarmos a dependência pom.xml, precisamos criar uma configuração separada da Spring, web-jamon-config.xml, que conterá a definição do bean para JamonPerformanceMonitorInterceptor.

Listagem 15. Conteúdo web-jamon-config.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:mvc="http://www.springframework.org/schema/mvc" \
xmlns:p="http://www.springframework.org/schema/p" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation=\
"http://www.springframework.org/schema/beans \
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd     
	http://www.springframework.org/schema/context \
http://www.springframework.org/schema/context/spring-context-3.0.xsd     
	http://www.springframework.org/schema/mvc \
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 


	<bean id="jamonPerformanceMonitorInterceptor" 
		class=\
"org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"> 
		<property name="trackAllInvocations" value="true"></property> 
		<property name="useDynamicLogger" value="true"></property> 
	</bean> 

	<bean id="autoProxyCreator" 
		class=\
"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
		<property name="interceptorNames"> 
			<list> 
				<idref bean="jamonPerformanceMonitorInterceptor" /> 
			</list> 
		</property> 
		<property name="beanNames"> 
			<list> 
				<value></value> 
			</list> 
		</property> 
	</bean> 

</beans>

No arquivo web-jamon-config.xml mostrado na Listagem 15, configuramos tudo que era necessário para JAMon em um aplicativo com base em Spring. A única coisa que não especifiquei foram os nomes dos beans a monitorar. O gerador de código não pode prever isto, portanto isto é deixado para que o desenvolvedor do complemento especifique.

Agora, precisamos escrever o código que copiará este arquivo web-jamon-config.xml para a pasta WEB_INF/spring, onde o webmvc-config.xml reside, e o código para a instrução add import em webmvc-config.xml para importar web-jamon-config.xml. (Veja a Listagem 16.)

Listagem 16. Código para manipular pom.xml
public void installJamon() { 
		 
	// update pom.xml code 
	PathResolver pathResolver =
        projectOperations.getProjectMetadata().getPathResolver(); 
	String resolvedSpringConfigPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP,
        "/WEB-INF/spring"); 
	if (fileManager.exists(resolvedSpringConfigPath + "/web-jamon-config.xml")) { 
			return; 
	} 
	copyTemplate("web-jamon-config.xml", resolvedSpringConfigPath); 
		 
	String webMvcConfigPath = resolvedSpringConfigPath + "/webmvc-config.xml"; 

	new XmlTemplate(fileManager).update(webMvcConfigPath, new DomElementCallback() { 
		public boolean doWithElement(Document document, Element root) { 
			if (null ==
               XmlUtils.findFirstElement\
("/beans/import[@resource='web-jamon-config.xml']",
                   root)) { 
                   Element element = document.createElement("import"); 
		        element.setAttribute("resource", "web-jamon-config.xml"); 
				root.appendChild(element); 
		        return true; 
		    } 
		    return false; 
		   } 
	}); 
		 
} 
	 
private void copyTemplate(String templateFileName, String resolvedTargetDirectoryPath) { 
	
    try { 
	    FileCopyUtils.copy(TemplateUtils.getTemplate(getClass(),
               templateFileName), fileManager.createFile(
	            resolvedTargetDirectoryPath + "/" +
                   templateFileName).getOutputStream()); 
	} catch (IOException e) { 
           throw new IllegalStateException(
               "Encountered an error during copying of resources for Jamon addon.", e); 
    } 
}

A classe XmlTemplate usada acima vem do complemento de fluxo da Web do Spring. Portanto, é preciso adicionar uma dependência para o complemento de fluxo da Web em seu complemento. (Veja a Listagem 17.)

Listagem 17. Adicionar dependência para o complemento de fluxo da Web
	<dependency> 
		<groupId>org.springframework.roo</groupId> 
		<artifactId>org.springframework.roo.addon.web.flow</artifactId> 
		<version>${roo.version}</version> 
      		<type>bundle</type> 
	</dependency>

Na Listagem 17, roo.version é a versão da Roo que você está usando.

A última coisa que precisamos fazer neste complemento é configurar o registro do projeto e configurar o nível de log a rastrear. Isso é feito usando LoggingOperations, que é uma classe de operações para o complemento log4j . Para usar esta classe, precisamos primeiro adicionar a dependência de complemento de criação de log no arquivo pom.xml, como mostra a Listagem 18.

Listagem 18. Código XML para adicionar dependência para o complemento de criação de log
	<dependency> 
		<groupId>org.springframework.roo</groupId> 
		<artifactId>org.springframework.roo.addon.logging</artifactId> 
		<version>${roo.version}</version> 
      		<type>bundle</type> 
	</dependency>

Depois de adicionar a dependência em pom.xml, adicione LoggingOperation na classe JamonOperationsImpl com a seguinte linha:

@Reference private LoggingOperations loggingOperations;

A seguir, adicione a seguinte linha ao método installJamon :

loggingOperations.configureLogging(LogLevel.TRACE, LoggerPackage.PROJECT);

Este é todo o código que precisamos escrever para este complemento. O código completo para a classe JamonOperationsImpl é mostrado na Listagem 19.

Listagem 19. Código completo para JamonOperationsImpl
@Component 
@Service 
public class JamonOperationsImpl implements JamonOperations { 
       @Reference private FileManager fileManager; 
       @Reference private ProjectOperations projectOperations; 
       @Reference private LoggingOperations loggingOperations; 


       public boolean isInstallJamonAvailable() { 
               return projectOperations.isProjectAvailable() && 
fileManager.exists(projectOperations.getPathResolver()
.getIdentifier(Path.SRC_MAIN_WEBAPP,"/WEB-INF/web.xml")); 
       } 


       public void installJamon() { 
               Element configuration = XmlUtils.getConfiguration(getClass()); 
               updatePomProperties(configuration); 
               updateDependencies(configuration); 
               PathResolver pathResolver = 
projectOperations.getProjectMetadata().getPathResolver(); 
               String resolvedSpringConfigPath = 
pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, 
            "/WEB-INF/spring"); 
               if (fileManager.exists(resolvedSpringConfigPath 
+ "/web-jamon-config.xml")) { 
                       return; 
               } 


               copyTemplate("web-jamon-config.xml", resolvedSpringConfigPath); 
                
               String webMvcConfigPath = resolvedSpringConfigPath 
+ "/webmvc-config.xml";


               new XmlTemplate(fileManager).update(webMvcConfigPath, 
new DomElementCallback() { 
                       public boolean doWithElement(Document document, Element root) {
                            if (null == XmlUtils.findFirstElement(
"/beans/import[@resource='web-jamon-config.xml']",
root)) { 
                                 
Element element = document.createElement("import"); 
                                element.setAttribute("resource", "web-jamon-config.xml"); 
                                root.appendChild(element); 
                                return true; 
                             } 
                             return false; 
                       } 
               });
               loggingOperations.configureLogging(LogLevel.TRACE, 
LoggerPackage.PROJECT); 
       } 
        
       private void copyTemplate(String templateFileName, 
String resolvedTargetDirectoryPath) { 
               try { 
FileCopyUtils.copy(
      TemplateUtils.getTemplate(getClass(), templateFileName),
              fileManager.createFile(resolvedTargetDirectoryPath + "/" + 
              templateFileName).getOutputStream()); 
               } catch (IOException e) { 
                       throw new IllegalStateException(
               "Encountered an error during copying of resources for Jamon addon.", e);
               } 
       } 
        
       private void updatePomProperties(Element configuration) { 
               List<Element> properties = XmlUtils
     .findElements("/configuration/jamon/properties/*",configuration);
               for (Element property : properties) { 
                       projectOperations.addProperty(new Property(property));
               } 
       } 


       private void updateDependencies(Element configuration) { 
               List<Dependency> dependencies = new ArrayList<Dependency>(); 
               List<Element> jamonDependencies = XmlUtils.findElements(
           "/configuration/jamon/dependencies/dependency", configuration); 
               for (Element dependencyElement : jamonDependencies) { 
                       dependencies.add(new Dependency(dependencyElement)); 
               } 
               projectOperations.addDependencies(dependencies); 
       } 
        
}

É possível fazer o download do código de origem completo deste complemento do repositório de código Google. Agora, vamos adicionar o suporte a JAMon a nosso aplicativo usando o complemento que acabamos de criar:

  1. Saia do shell roo e execute o comando mvn clean install. Durante o processo de compilação, será solicitada a passphrase GPG.
  2. Depois da compilação do complemento da Roo, abra uma nova linha de comando e crie um diretório chamado jamon-client. Criaremos um cliente simples para nosso complemento.
  3. Acesse o diretório jamon-client e digite o comando roo para abrir um shell da Roo.
  4. Execute os comandos da Listagem 20 no shell da Roo. Isto criará um aplicativo da Web Spring MVC simples.
    Listagem 20. Criar aplicativo da Web MVC simples
    project --topLevelPackage com.shekhar.roo.jamon.client --projectName jamon-client 
    persistence setup --provider HIBERNATE --database
    HYPERSONIC_IN_MEMORY
    entity --class ~.domain.MyUser
    field string --fieldName name --notNull
    controller all --package ~.web
  5. Para instalar o complemento, digite:
    osgi start --url <a
    href="../../../../">file:///</a><location \
    to addon target folder >
    /org.xebia.roo.addon.jamon-0.1.0.BUILD-SNAPSHOT.jar

    Isto deverá instalar e ativar nosso complemento JAMon. É possível visualizar o status do complemento usando o comando osgi ps.

  6. Digite o comando jamon setup e verá o JAMon sendo configurado em seu aplicativo. Se executar seu aplicativo agora usando mvn tomcat:run, você não verá logs no console, pois não configurou quaisquer beans para monitoração. Vamos configurar nosso bean myUserController no web-jamon-config.xml com o código da Listagem 21.
    Listagem 21. Configuração para myUserController em web-jamon-config.xml
    	<bean id="autoProxyCreator" 
    		class=\
    "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
    		<property name="interceptorNames"> 
    			<list> 
    				<idref bean="jamonPerformanceMonitorInterceptor" /> 
    			</list> 
    		</property> 
    		<property name="beanNames"> 
    			<list> 
    				<value>myUserController</value> 
    			</list> 
    		</property> 
    	</bean>
  7. Agora, execute o aplicativo usando mvn tomcat:run e verá logs do JAMon em seu console maven. Uma amostra é exibida na Listagem 22.
    Listagem 22. Amostra de log do JAMon
    TRACE MyUserController - JAMon performance statistics for method 
    [MyUserController.populateMyUsers]: 
    JAMon Label=MyUserController.populateMyUsers, Units=ms.: (LastValue=187.0, 
    Hits=1.0, Avg=187.0, Total=187.0, Min=187.0, Max=187.0, Active=0.0, Avg 
    Active=1.0, Max Active=1.0, First Access=Wed May 18 15:33:41 IST 2011, Last 
    Access=Wed May 18 15:33:41 IST 2011)

Depois de testar se seu complemento está funcionando no sistema de desenvolvimento, é possível enviá-lo para o projeto de código Google que criamos. Para publicar o complemento para o mundo externo, siga o mesmo procedimento usado para o complemento i18n. Da mesma forma, para registrar o complemento no RooBot, siga o procedimento de registro do i18n.


Conclusão

Vimos a arquitetura de complemento do Spring Roo e como escrever complementos de internacionalização e complementos simples. A arquitetura de complementos é importante para a Roo porque dá à Roo a flexibilidade de adicionar novos recursos rapidamente. Para desenvolvedores, esta arquitetura de complementos é importante, pois permite que atendam a seus requisitos sem ter que aguardar que recursos sejam implementados globalmente. Posteriormente, se um recurso for incorporado na Roo, será relativamente fácil alterar a implementação para remover a solução personalizada.

Na Parte 4 desta série "Introdução à Spring Roo", falarei sobre como você pode escrever complementos advanced e wrapper.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

  • Participe dos Blogs do developerWorks e participe da comunidade do developerWorks.
  • Participe dos comunidade do developerWorks. Entre em contato com outros usuários do developerWorks, enquanto explora os blogs, fóruns, grupos e wikis orientados ao desenvolvedor.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=754929
ArticleTitle=Introdução ao Spring Roo, Parte 3: Desenvolvimento de complementos do Spring Roo
publish-date=08312011