A parte 3 desta série, “Apresentando o Spring Roo”, discute a arquitetura de complementos do Spring Roo e como criar internacionalização e complementos simples usando o comando criar complemento
. Este artigo foca os dois tipos restantes de complementos suportados pelo Spring Roo, isto é, complemento avançado e de wrapper. Recomenda-se que a Parte 3 seja consultada antes de continuar.
Introdução ao complemento avançado
O complemento avançado permite que o Spring Roo faça tudo que um complemento simples pode fazer, como atualizar um arquivo Maven POM com dependências ou plug-ins, atualizar ou incluir arquivos de configuração, além de aprimorar tipos Java existentes e introduzir novos tipos Java usando AspectJ ITDs. A capacidade de incluir um código fonte torna os complementos avançados muito eficientes em comparação a todos os demais complementos. Antes de criar um complemento avançado do Spring Roo, considere um complemento avançado existente fornecido pelo Spring Roo.
Complemento avançado em ação
Um complemento avançado é o JPA, que executa trabalho relacionado à persistência, isto é, incluindo suporte para bancos de dados e criando novas entidades. Para visualizar isso em ação, abra o shell Roo e execute os comandos em Lista 1. Neste artigo, o Spring Roo versão 1.2.0.M1 é utilizado.
project --topLevelPackage com.dw.demo --projectName entity-demo jpa setup --database FIREBIRD --provider HIBERNATE entity --class ~.domain.Book
Ambos os comandos configuração de jpa
e entidade
correspondem a um complemento avançado chamado org.springframework.roo.addon.jpa
. A saída dos comandos configuração de jpa
e entidade
no shell Roo possibilita uma clara distinção entre complementos simples e avançados. Lista 2 mostra a saída do comando configuração de JPA.
Created SRC_MAIN_RESOURCES/META-INF/spring/database.properties Updated ROOT/pom.xml [added dependencies ...] Updated SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml Created SRC_MAIN_RESOURCES/META-INF/persistence.xml
A saída do comando configuração de jpa
mostra que ele está executando funções de configuração, como a inclusão de dependências em pom.xml, atualizando o applicationContext.xml do Spring e criando o persistence.xml específico à persistência. Presume-se que o comando de configuração de JPA corresponda a um complemento simples, porque não está criando ou atualizando o código fonte Java. Use um complemento simples para cenários semelhantes à configuração mostrada acima.
Lista 3 mostra a saída do comando entidade
especificado.
Created SRC_MAIN_JAVA/com/dw/demo/domain Created SRC_MAIN_JAVA/com/dw/demo/domain/Book.java Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Configurable.aj Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Jpa_Entity.aj Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Entity.aj Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_ToString.aj
A saída mostra a criação de um arquivo Java chamado Book.java e quatro arquivos *.aj. A regra final para identificar um complemento avançado é a geração de arquivos Java ou *.aj, ou ambos, como no caso do comando de entidade. Esses *Roo_*.aj são chamados de Inter-type Declarations (ou ITDs). As ITDs permitem um tipo (um aspecto) para fazer declarações para outro tipo, isto é, é possível modificar a estrutura estática de qualquer tipo incluindo métodos, campos ou alterando sua hierarquia de tipo. O Roo usa uma ITD como um artefato de geração de códigos e os gerencia durante todo o seu tempo de vida. As ITDs permitem que o Roo gere um código em uma unidade de compilação separada, mas elas são combinados na mesma classe compilada.
Após visualizar a saída do comando entidade, considere como esses artefatos (arquivos .java e.aj) são gerados pelo Spring Roo. Consultea Lista 4 para obter uma amostra de um arquivo Book.java.
package com.dw.demo.domain; import org.springframework.roo.addon.entity.RooEntity; import org.springframework.roo.addon.javabean.RooJavaBean; import org.springframework.roo.addon.tostring.RooToString; @RooJavaBean @RooToString @RooEntity public class Book { }
O arquivo Java parece normal, exceto para anotações na classe. Observando os nomes da anotação e os arquivos .aj, nota-se que algumas dessas anotações correspondem à funcionalidade incluída por arquivos .aj. Por exemplo: RooToString
corresponde ao arquivo Book_Roo_ToString.aj e ao método incluir toString()
. RooEntity
corresponde a Book_Roo_Entity .aj, Book_Roo_Jpa_Entity
e métodos relacionados à persistência. Deixemos o resto de lado por ora. Para entender como essas anotações levam à geração de ITDs, explore como o Spring Roo fornece funcionalidades de complemento avançado.
- Na inicialização de shell Roo, ele varrerá todas as classes e registrará todas as que implementam a interface
CommandMarker
.A interface CommandMarker
informa ao Roo que essas classes definirão os comandos que esse complemento pode executar; - Todos os complementos avançados registram seus serviços no tempo de execução de OSGi fornecido pelo Spring Roo. Esses serviços especificam condições nas quais ele acionará a geração de códigos. Para todos os complementos avançados, o ponto de acionamento é a presença de uma anotação. Por exemplo, um complemento avançado para a geração do método
toString()
é acionado somente se um tipo Java tiver a anotação RooToString. Esse é o caso com outras anotações; - Mediante o uso de
entity --class ~.domain.Book
, o complemento criará um arquivo Java chamado Book.java com anotações. Outros complementos são acionados quando um tipo Java tem essas anotações e os arquivos .aj são gravados para eles.
Um maior esclarecimento será evidente quando criar seu próprio complemento avançado.
O complemento org.springframework.roo.addon.jpa
é apenas um exemplo de complemento avançado fornecido pelo Spring Roo. Outros complementos avançados incluem: GWT, controlador, JSON e muito mais. A liberação do Spring Roo 1.2.0 contém mais dois complementos avançados:—addon-equals e addon-jsf. O addon-equals fornece implementação para métodos equivalentes e código hash para uma entidade e o addon-jsf fornece suporte a JSF em aplicativos Spring Roo. Para a reprodução da captura instantânea mais recente do Spring Roo, crie o código do Spring Roo ou faça o download da captura instantânea noturna do repositório do Spring Roo.
Inclua o método compareTo() na minha classe de entidade
Os objetos de valor ou entidades são comumente necessários para implementar a interface java.lang.Comparable e fornecer a implementação para o método compareTo()
. A interface comparável impõe ordenação total sobre os objetos de cada classe que a está implementando. Quando Comparável é implementado, é possível:
- Chamar
java.util.Collections.sort
ejava.util.Collections.binarySearch;
- Chamar
java.util.Arrays.sort
ejava.util.Arrays.binarySearch;
- Usar objetos como chaves em um
java.util.TreeMap;
- Usar objetos como elementos em um
java.util.TreeSet.
Neste artigo, será criado um complemento avançado que fornecerá uma implementação de compareTo()
para entidades criadas em seu aplicativo. Como deseja incluir o código Java em seu aplicativo, é preciso criar um complemento avançado.
Configuração do Projeto
A documentação do Spring Roo explica de forma eloquente como configurar um projeto e um repositório Maven no código do Google; portanto, é desnecessário repeti-lo aqui. Observe que “spring-dw-roo-compareto-addon” será usado como o nome do projeto.
Caso não esteja usando a versão mais recente do Spring Roo, 1.2.0.RC1, faça download dela no website do projeto. Descompacte e instale essa versão conforme explicado na parte 1.
O Spring Roo descontinuou ou removeu algumas das classes usadas em versões anteriores.
Criando um complemento avançado
Após configurar o projeto, será possível visualizar um diretório chamado spring-dw-roo-compareto-addon com apenas uma pasta .svn. Na linha de comandos, acesse o diretório spring-dw-roo-compareto-addon e inicie o shell Roo. Então, digite o comando a seguir:
addon create advanced --topLevelPackage org.xebia.roo.addon.compareto --projectName spring-dw-roo-compareto-addon
Pronto! Um complemento avançado acabou de ser criado.
Em seguida, no shell Roo, dispare o comando realizar pacote
para criar um complemento jar. Lista 5 mostra os arquivos gerados pelo complemento criar avançado
.
Created ROOT/pom.xml Created SRC_MAIN_JAVA Created SRC_MAIN_RESOURCES Created SRC_TEST_JAVA Created SRC_TEST_RESOURCES Created SPRING_CONFIG_ROOT Created ROOT/readme.txt Created ROOT/legal Created ROOT/legal/LICENSE.TXT Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoCommands.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoOperations.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoOperationsImpl.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoMetadata.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoMetadataProvider.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/RooCompareto.java Created ROOT/src/main/assembly Created ROOT/src/main/assembly/assembly.xml Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/compareto Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/compareto/configuration.xml
Alguns dos arquivos gerados, como pom.xml, readme.txt e license.txt, não precisam de introdução, pois foram apresentados na parte 3 e são autoexplicativos. Os artefatos mais interessantes são:
- ComparetoCommands.java;
- ComparetoOperations.java;
- ComparetoOperationsImpl.java;
- ComparetoMetadata.java;
- ComparetoMetadataProvider.java;
- RooCompareto.java.
Agora, veremos os artefatos gerados um a um.
ComparetoCommands.java
: Esta classe implementa a interfaceCommandMarker
e expõe dois tipos de métodos:—um com a anotaçãoCliAvailablityIndicator
e outro com a anotaçãoCliCommand
. A anotaçãoCliAvailablityIndicator
informa ao Spring Roo quando o comando deve estar visível. Por exemplo, o comando ‘entidade
‘ não será disponibilizado antes de o usuário definir as configurações de persistência no shell Roo ou diretamente no projeto. Os métodos anotados com@CliCommand
registram o comando com o shell Roo. A anotação@CliCommand
possui dois atributos: valor, que define o nome do comando; e ajuda, que define a mensagem de ajuda exibida quando o comando de ajuda é digitado. Para obter uma explicação detalhada da classe*Commands
, consulte a parte 3.ComparetoOperationsImpl.java
: A classeComparetoCommands
delega todo o trabalho para a classeComparetoOperationsImpl
. Os quatro métodos gerados nesta classe são:isCommandAvailable()
: Este método é chamado pelo método anotado comCliAvailabilityIndicator ComparetoCommands
na classeComparetoCommands
para verificar se o comando deve estar visível ou não. Isso é para assegurar que os comandos estejam cientes do contexto. Este método executa várias validações. Por exemplo, se o projeto tiver sido criado, somente o comando estará visível; ou se a persistência tiver sido configurada, somente o comando deverá estar visível. Não é obrigatório ter uma condição para que o comando esteja visível. Simplesmente retorne verdade para garantir que o comando esteja sempre visível.setup()
: Este método é chamado pelo métodosetup()
, na classeComparetoCommands
que é anotada com@CliCommand
. O código esclarece que esta classe é responsável por executar tarefas relacionadas à configuração, como incluir dependências Maven, incluir repositórios Maven ou criar ou atualizar arquivos de contexto do Spring (como no complemento Jamon Roo na parte 3).annotateType()
: Este método eannotateAll()
são novos métodos que não existem em complementos simples. A funcionalidade deste método é incluir uma anotação (RooCompareto
) no tipo Java especificado. Este método utiliza alguns serviços fornecidos pelo Spring Roo para buscar os detalhes da Classe para o tipo Java determinado e anexar a anotaçãoRooJCompareto
a ele.annotateAll()
: Este método encontra todos os tipos que são anotados com a anotaçãoRooJavaBean
e chama o métodoannotateType()
em todos esses tipos. Utilize este método quando todas as entidades forem obrigadas a ter a anotaçãoRooCompareto
.
RooCompareto.java
: A presença desta anotação aciona o complemento para gerar o código.ComparetoMetadataProvider.java
: Esta classe é um serviço do Spring Roo e é chamada pelo Roo para recuperar os metadados para o complemento. Esta classe registra acionadores para incluir e remover metadados. Nenhuma mudança é necessária nesta classe, mas lembre-se que ela tem um método chamado getMetadata() que será chamado pelo Spring Roo sempre que houver qualquer tipo Java com a anotaçãoRooCompareto
.ComparetoMetadata.java
: Esta classe é responsável por gerar o ITD correspondente ao complemento. No código gerado, ela usa uma classe chamadaItdTypeDetailsBuilder
para criar uma ITD com um campo e um método. Posteriormente neste artigo, você alterará o código padrão gerado para atender aos requisitos de incluir um métodocompareTo
e implementar a interface Comparável.
Modificando o complemento para atender aos requisitos
Você deseja criar um complemento que deve incluir o método compareTo
para classes de entidade. Será preciso:
Incluir a dependência Maven commons-lang
versão 3.1 no projeto de destino. Isso é necessário, porque commons-lang
fornece uma classe de construtor chamada CompareToBuilder
que será usada para criar o método compareTo
.
- Faça com que a classe de entidade implemente a interface
Comparável
; - Crie uma ITD para o método
compareTo
.
Incluindo a dependência maven
Para atender a esses requisitos, as mudanças são necessárias nas classes ComparetoOperationsImpl
e ComparetoMetadata
. Faça uma mudança de cada vez.
- Primeiro, inclua a dependência Maven
commons-lang
no projeto de destino. Atualize o arquivo configuration.xml para que tenha a dependênciacommons-lang
em vez da dependência de lote do Spring fornecida padrão, como em Lista 6.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.1</version> </dependency> </dependencies> </configuration>
Em seguida, modifique a implementação do método setup()
na classe ComparetoOperationsImpl
para ler a dependência Maven commons-lang
em vez da dependência Maven de lote do Spring, como em Lista 7. O método annotateType
e annotateAll()
não são mostradas aqui, porque eles não apresentam mudanças.
@Component @Service public class ComparetoOperationsImpl implements ComparetoOperations { @Reference private ProjectOperations projectOperations; @Reference private TypeLocationService typeLocationService; @Reference private TypeManagementService typeManagementService; /** {@inheritDoc} */ public void setup() { // Install the add-on Google code repository needed to get the annotation projectOperations.addRepository("", new Repository("Compareto Roo add-on repository", "Compareto Roo add-on repository", "https://spring-dw-roo-compareto-addon.googlecode.com/svn/repo")); List<Dependency> dependencies = new ArrayList<Dependency>(); // Install the dependency on the add-on jar ( dependencies.add(new Dependency("org.xebia.roo.addon.compareto", "org.xebia.roo.addon.compareto", "0.1.0.BUILD-SNAPSHOT", DependencyType.JAR, DependencyScope.PROVIDED)); Element configuration = XmlUtils.getConfiguration(getClass()); for (Element dependencyElement : XmlUtils.findElements( "/configuration/dependencies/dependency", configuration)) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies("", dependencies); } }
As mudanças feitas até agora são semelhantes às mudanças usadas para criar um complemento simples Jamon na parte 3.
Faça com que a classe de entidade implemente a interface comparável
Após fazer mudanças no código para incluir a dependência Maven, é necessário garantir que sua classe de entidade implemente a interface java.lang.Comparable. Para fazer isso, modifique a ITD gerada pela classe ComparetoMetadata
. As classes de metadados geram a ITD usando a classe ItdTypeDetailsBuilder
que fornece vários métodos de inclusão para incluir métodos, campos, anotações, interface, entre outros, em uma ITD. Para fazer com que um tipo Java implemente uma interface, use o método addImplementsType
na classe ItdTypeDetailsBuilder
, como na Lista 8. Somente o construtor ComparetoMetadata
é exibido porque a construção da ITD ocorre nele.
public ComparetoMetadata(String identifier, JavaType aspect Name, PhysicalTypeMetadata governorPhysicalTypeMetadata) { super(identifier, aspect Name, governorPhysicalTypeMetadata); Assert.isTrue(isValid(identifier), "Metadata identification string '" + identifier + "' does not appear to be a valid"); JavaType comparableInterface = new JavaType("java.lang.Comparable"); builder.addImplementsType(comparableInterface); itdTypeDetails = builder.build(); }
Crie uma ITD para o método compareTo
Após fazer com que um tipo Java implemente a interface Comparável, é preciso fornecer a implementação do método compareTo. A classe CompareToBuilder fornece uma interface fluente para criar o método compareTo. O complemento equivalentes do Spring Roo usa o EqualsBuilder e o HashcodeBuilder para fornecer a implementação para os métodos equivalentes e código hash. Usaremos um exemplo para garantir que haja dúvidas sobre como o CompareToBuilder
auxilia na criação do método compareTo
. Suponhamos que você tenha uma entidade chamada Book e deseja fornecer a implementação compareTo para ela usando o CompareToBuilder
. Lista 9 mostra a classe Book e compareTo
.
import org.apache.commons.lang3.builder.CompareToBuilder; public class Book implements Comparable { private String title; private String author; private double price; public Book(String title, String author, double price) { this.title = title; this.author = author; this.price = price; } // getters and setters public int compareTo(Book o) { if(!(o instanceof Book)){ return -1; } Book book = (Book)o return new CompareToBuilder().append(this.title, book.title).append(this.author, book.author).append(this.price, book.price).toComparison(); } @Override public String toString() { return "Book [title=" + title + ", author=" + author + ", price=" + price + "]"; } }
O método compareTo
na Lista 9 faz o seguinte:
- Se “o” não for
instanceOfBook
, retorne -1; - Se “o” for
instanceOfBook
, digite cast o para Book; - Crie um objeto da classe
CompareToBuilder
e, em seguida, chame o método anexar nos campos.
Crie o método compareTo
incrementalmente com estas etapas:
- Se “o” não for instanceOf Book, retorne -1
Antes de incluir a verificação instanceOf
, crie o método compareTo
. Consulte Lista 10.
public ComparetoMetadata(String identifier, JavaType aspect Name, PhysicalTypeMetadata governorPhysicalTypeMetadata) { super(identifier, aspect Name, governorPhysicalTypeMetadata); Assert.isTrue(isValid(identifier), "Metadata identification string '" + identifier + "' does not appear to be a valid"); JavaType comparableInterface = new JavaType("java.lang.Comparable"); builder.addImplementsType(comparableInterface); builder.addMethod(getCompareToMethod()); itdTypeDetails = builder.build(); } private MethodMetadata getCompareToMethod() { final JavaType parameterType = JavaType.OBJECT; final List parameterNames = Arrays.asList(new JavaSymbolName("obj")); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine("return -1;"); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName("compareTo"), JavaType.INT_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterType), parameterNames, bodyBuilder); return methodBuilder.build(); }
O getCompareToMethod()
gera os metadados do método compareTo
usando a classe MethodMetadataBuilder
. MethodMetadataBuilder
é uma classe Builder
fornecida pelo Spring Roo para criação de metadados de método. Para criar os metadados de método, primeiro construa um objeto MethodMetadataBuilder
, passando argumentos, como modificador de acesso, nome de método, tipo de retorno, lista de parâmetros ou um construtor de corpo de método para criar os metadados para o método compareTo
como na Lista 11.
private MethodMetadata getCompareToMethod() { final JavaType parameterType = JavaType.OBJECT; String parameterName = "obj"; final List parameterNames = Arrays.asList(new JavaSymbolName(parameterName)); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); final String typeName = destination.getSimpleTypeName(); bodyBuilder.appendFormalLine("if (!(" + parameterName + " instanceof " + typeName + ")) {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("return -1;"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); bodyBuilder.appendFormalLine("return -1;"); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName("compareTo"), JavaType.INT_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterType), parameterNames, bodyBuilder); return methodBuilder.build(); }
- Se “o” for
instanceOfBook
, digite cast o para Book
A próxima etapa é um cast, portanto, é possível criar o método compareTo
. Para fazer isso, anexe esta linha após a verificação instanceOf:
bodyBuilder.appendFormalLine(typeName + " rhs = (" + typeName + ") " + OBJECT_NAME + ";");
- Crie o objeto da classe CompareToBuilder e, em seguida, chame o método anexar nos campos
Para criar o método compareTo
, é necessário acesso a todos os campos de uma classe. A classe ComparetoMetadata
não contém nenhuma informação sobre o tipo, portanto, não é possível obter campos da classe. Essas informações podem ser fornecidas pelo ComparetoMetadataProvider
como na Lista 12.
protected ItdTypeDetailsProvidingMetadataItem getMetadata(String metadataId, JavaType aspect Name, PhysicalTypeMetadata governorPhysicalTypeMetadata, String itdFilename) { final String[] excludeFields = {}; final MemberDetails memberDetails = getMemberDetails(governorPhysicalTypeMetadata); if (memberDetails == null) { return null; } final JavaType javaType = governorPhysicalTypeMetadata.getMemberHoldingTypeDetails().getName(); final List compareToFields = locateFields(javaType, excludeFields, memberDetails, metadataId); return new ComparetoMetadata(metadataId, aspect Name, governorPhysicalTypeMetadata, compareToFields); } private List locateFields(final JavaType javaType, final String[] excludeFields, final MemberDetails memberDetails, final String metadataIdentificationString) { final SortedSet locatedFields = new TreeSet(new Comparator() { public int compare(final FieldMetadata l, final FieldMetadata r) { return l.getFieldName().compareTo(r.getFieldName()); } }); final List excludeFieldsList = CollectionUtils.arrayToList(excludeFields); final FieldMetadata versionField = persistenceMemberLocator.getVersionField(javaType); for (final FieldMetadata field : memberDetails.getFields()) { if (excludeFieldsList.contains(field.getFieldName().getSymbolName())) { continue; } if (Modifier.isStatic(field.getModifier()) || Modifier.isTransient(field.getModifier()) || field.getFieldType().isCommonCollectionType() || field.getFieldType().isArray()) { continue; } if (versionField != null && field.getFieldName().equals(versionField.getFieldName())) { continue; } locatedFields.add(field); metadataDependencyRegistry.registerDependency( field.getDeclaredByMetadataId(), metadataIdentificationString ); } return new ArrayList(locatedFields); }
Quando tiver os campos, passe-os para ComparetoMetadata
a fim de que possa criar o método compareTo
, como mostra a Lista 13.
private List compareToFields; public ComparetoMetadata(String identifier, JavaType aspectName, PhysicalTypeMetadata governorPhysicalTypeMetadata, List compareToFields) { super(identifier, aspectName, governorPhysicalTypeMetadata); Assert.isTrue(isValid(identifier), "Metadata identification string '" + identifier + "' does not appear to be a valid"); this.compareToFields = compareToFields; if (!CollectionUtils.isEmpty(compareToFields)) { JavaType comparableInterface = new JavaType("java.lang.Comparable"); builder.addImplementsType(comparableInterface); builder.addMethod(getCompareToMethod()); } itdTypeDetails = builder.build(); } private MethodMetadata getCompareToMethod() { final JavaType parameterType = JavaType.OBJECT; String parameterName = "obj"; final List parameterNames = Arrays.asList(new JavaSymbolName(parameterName)); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); final ImportRegistrationResolver imports = builder.getImportRegistrationResolver(); imports.addImport( newJavaType("org.apache.commons.lang3.builder.CompareToBuilder") ); final String typeName = destination.getSimpleTypeName(); bodyBuilder.appendFormalLine("if (!(" + parameterName + " instanceof " + typeName + ")) {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("return -1;"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); bodyBuilder.appendFormalLine(typeName + " rhs = (" + typeName + ") " + parameterName + ";"); final StringBuilder builder = new StringBuilder(); builder.append("return new CompareToBuilder()"); for (final FieldMetadata field : compareToFields) { builder.append(".append(" + field.getFieldName() + ", rhs." + field.getFieldName() + ")"); } builder.append(".toComparison();"); bodyBuilder.appendFormalLine(builder.toString()); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName("compareTo"), JavaType.INT_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterType), parameterNames, bodyBuilder); return methodBuilder.build(); }
Teste
Isso conclui a implementação do complemento compareTo
. É possível fazer download do código de origem completo deste complemento a partir do repositório de código do Google. Agora, é possível testar o compareTo
que acabou de ser criado.
- Saia do shell roo e execute o comando
instalação limpa do mvn
. Durante o processo de construção, será solicitada a passphrase GPG; - Após o complemento do Roo ser criado, abra uma nova linha de comandos e crie um diretório chamado livraria;
- Acesse o diretório livraria e digite o comando
roo
para abrir um shell Roo; - Execute os comandos de Lista 14 no shell Roo.
project --topLevelPackage com.xebia.roo.bookshop --projectName bookshop jpa setup --database HYPERSONIC_IN_MEMORY --provider HIBERNATE entity jpa --class ~.domain.Book field string --fieldName title --notNull field string --fieldName author --notNull field number --fieldName price --type double --notNull
- Para instalar e iniciar o complemento, digite o que segue no shell Roo:
osgi start --url file://<location to compareTo addon jar>
Isso deverá instalar e ativar seu complemento compareTo. É possível visualizar o status do complemento usando o comando OSGi ps.
- Digite
compareto
e pressione tab para visualizar os três comandos do complemento compareto na Lista 15.
roo> compareto compareto add compareto all compareto setup
- As etapas configuradas na Lista 15 confirmará se o complemento compareto está adequadamente instalado. A próxima etapa é executar o comando configuração, que configurará as dependências necessárias. Consulte Lista 16.
roo> compareto setup Updated ROOT/pom.xml [added repository https://spring-dw-roo-compareto-addon.googlecode.com/svn/repo; added dependencies org.xebia.roo.addon.compareto:org.xebia.roo.addon.compareto: 0.1.0.BUILD, org.apache.commons:commons-lang3:3.1; removed dependency org.apache.commons:commons-lang3:3.0.1]
- Quando executar o comando
compareto setup
a próxima etapa lógica é incluir o métodocompareTo
em classes de entidade. Isso pode ser feito por meio de compareto add ou compareto all, dependendo se deseja gerar o método compareTo para somente uma classe de entidade ou todas as classes de entidade. Incluiremos o métodocompareTo
em todas as classes de entidade na amostra do aplicativo bookshop (consulte Downloads). Consulte Lista 17.
roo> compareto all Updated SRC_MAIN_JAVA/com/xebia/roo/bookshop/domain/Book.java Created SRC_MAIN_JAVA/com/xebia/roo/bookshop/domain/Book_Roo_Compareto.aj
Como pode ver acima, na saída do comando compareto all, um ITD chamado Book_Roo_Compareto.aj é gerado. Esse arquivo conterá o método compareTo. A Lista 18 mostra o Book_Roo_Compareto.aj.
import org.apache.commons.lang.builder.CompareToBuilder; privileged aspect Book_Roo_Compareto { declare parents: Book implements java.lang.Comparable; public int Book.compareTo(java.lang.Object obj) { if (!(obj instanceof Book)) { return -1; } Book rhs = (Book) obj; return new CompareToBuilder().append(author, rhs.author).append(id, rhs.id).append(price, rhs.price).append(title, rhs.title).toComparison(); } }
- Execute o comando
realizar pacote
no shell Roo para verificar se tudo está compilado corretamente após incluir o complemento. Para sua surpresa, a construção falhará porque o Maven não consegue resolver dependências do pacote configurável do Sprin Roo. Essas dependências de pacote configurável vêm do complementocompareTo
. É necessária a dependência do complemento, porque suas entidades têm de ser anotadas com a anotação Compareto. Essa é a única coisa que precisa do complemento. A melhor forma encontrada é criar outro módulo Maven e ter todas as dependências do complemento lá. É semelhante com o que o Sprin Roo faz. O Spring Roo não cria dependência com cada complemento usado. Ele possui anotações jar de Spring Roo comuns que contêm todas as dependências. O xebia-spring-roo-addon-annotation do projeto foi criado e a anotação Compareto foi inserida neste módulo. Em seguida, o configuration.xml foi atualizado para incluir esse jar no projeto do cliente, em vez do jar do complemento. A Lista 19 mostra o configuration.xml.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>org.xebia.roo.addon</groupId> <artifactId>xebia-spring-roo-addon-annotations</artifactId> <version>0.0.1</version> </dependency> </dependencies> <repositories> <repository> <id>spring-roo-addon-annoations</id> <name>Spring Roo Addon Annotation</name> <url>https://xebia-spring-roo-addon-annotations.googlecode.com/svn/repo</url> </repository> </repositories> </configuration>
Atualize a classe ComparetoOperationsImpl
do método setup()
para ler as novas dependências e repositórios especificados no arquivo configuration.xml atualizado. Consulte Lista 20.
public void setup() { bu
List<Dependency> dependencies = new ArrayList<Dependency>(); Element configuration = XmlUtils.getConfiguration(getClass()); for (Element dependencyElement : XmlUtils.findElements("/configuration/dependencies/dependency", configuration)) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies("", dependencies); List<Element> repositories = XmlUtils.findElements( "/configuration/repositories/repository", configuration); for (Element repositoryElement : repositories) { Repository repository = new Repository(repositoryElement); projectOperations.addRepository(projectOperations.getFocusedModuleName(), repository); } }
Em seguida, siga estas etapas:
- Crie o complemento novamente executando
instalação limpa do mvn
. - Gere novamente o cliente como na etapa 4.
- Para remover o complemento antigo, digite este comando no shell Roo:
addon remove --bundleSymbolicName org.xebia.roo.addon.compareto
- Instale o complemento novamente executando o comando
osgi install
; - Quando o complemento for instalado, execute os comandos
compareto setup
ecompareto all
;
As ITDs compareTo poderão ser visualizadas. Execute o comando realizar pacote e tudo funcionará direito.
Quando testar que seu complemento está funcionando em seu ambiente de desenvolvimento, será possível realizar seu push para o projeto do código do Google criado. Para publicar o complemento para o mundo, siga o mesmo procedimento usado para publicar o complemento i18n na parte 3. Da mesma forma, para registrar o complemento com o RooBot, siga a documentação do Spring Roo.
Torne os drivers JDBC não OSGi compatíveis com OSGi com o complemento de wrapper
Um caso de uso comum do complemento de wrapper é para a conversão de drivers JDBC não OSGi para pacotes configuráveis compatíveis com OSGi. Um local em que é necessário quebrar um driver JDBC é quando você tem de realizar engenharia reversa em um banco de dados Oracle usando o Roo. O Spring Roo não fornece drivers JDBC Oracle OSGi, devido a problemas de copyright. Antes de fazer a engenharia reversa de um banco de dados Oracle, primeiro torne o driver compatível com OSGi. Para criar um complemento de wrapper para um driver JDBC Oracle:
- Instale o jar JDBC Oracle em seu repositório Maven da máquina local digitando este comando
mvn install:install-file -Dfile=ojdbc5.jar -DgroupId=com.oracle -DartifactId=ojdbc5 -Dversion=11.2.0.2 -Dpackaging=jar
- Crie um novo diretório chamado oracle-wrapper-addon e, a partir da linha de comandos, acesse o diretório.
- Abra o shell Roo e execute o comando de complemento de wrapper:
addon create wrapper --topLevelPackage com.oracle.wrapper.jdbc --groupId com.oracle --artifactId ojdbc5 --version 11.2.0.2 --vendorName Oracle --licenseUrl oracle.com
Esse comando gerará somente arquivos pom.xml que serão usados para converter um driver JDBC Oracle não OSGi em um driver OSGi - De dentro do shell Roo, excute este comando para criar o pacote configurável do OSGi:
perform command --mavenCommand bundle:bundle
Pronto. Um pacote configurável de OSGi foi criado com sucesso a partir de um jar não OSGi.
Conclusão
Neste artigo, você aprendeu sobre o complemento avançado e de wrapper no Spring Roo. Também aprendeu a criar complementos avançados e de wrapper. Isso conclui sua exploração em um recurso muito importante do Spring Roo: gravação de complementos. Sempre que desejar estender a funcionalidade do Spring Roo, lembre-se de pensar sobre a criação de complementos.
Na próxima parte desta série, “Apresentando o Spring Roo”, será discutido como gravar aplicativos GWT usando o Spring Roo.
Downloads
Descrição | Nome | Tamanho | Método de download |
---|---|---|---|
Sample code | bookshop.zip | 14KB | HTTP |
Sample code | spring-dw-roo-compareto-addon.zip | 18KB | HTTP |
Informações sobre métodos de download
Recursos
Aprender
- Explore a documentação do Spring Roo e encontre tudo de que precisa para usar o Roo efetivamente.
- Certifique-se de ler o resto desta série do Spring Roo:
- Busque o código para Spring Roo nesta visualização na web do Código Fonte do Spring Roo.
- Saiba mais sobre o java.lang.Comparable .
- Leia a documentação do Spring Roo sobre como configurar um projeto e repositório Maven no código do Google.
- Acompanhe a documentação do Spring Roo para registrar o complemento com o RooBot.
- Na área de Software Livre no developerWorks, encontre informações extensas sobre instruções, ferramentas e atualizações de projetos para ajudar no desenvolvimento com tecnologias de software livre e usá-las com produtos IBM.
- Na zona de tecnologia Java do developerWorks, encontre artigos, tutoriais, fóruns, entre outros, sobre cada aspecto da programação Java.
- Fique por dentro dos eventos técnicos e webcasts do developerWorks com ênfase em uma série de produtos IBM e tópicos do segmento de mercado de TI.
- Participe de um resumo de instruções gratuito do developerWorks para se atualizar rapidamente sobre produtos e ferramentas IBM e tendências do segmento de mercado de TI.
- Ouça os podcasts do developerWorks para obter entrevistas e discussões interessantes para os desenvolvedores de software.
- Siga o developerWorks no Twitter.
- Assista às demos do developerWorks que variam de instalação e configuração de produtos para iniciantes a funcionalidades avançadas para desenvolvedores experientes.
Obter produtos e tecnologias
- Acesse o website do repositório do Spring Roo para fazer download da captura instantânea noturna do código.
- Faça download da versão mais recente do Spring Roo, 1.2.0.RC1 a partir do website do projeto.
- Faça download do código fonte integral do complemento compareTo do repositório do código Google.
- Acessea versão de teste do software IBM (disponível para download ou no DVD) e inove em seu próximo projeto de desenvolvimento de software livre usando o software especialmente para desenvolvedores.
Discutir
Conecte-se com outros usuários do developerWorks enquanto explora os blogs, fóruns, grupos e wikis voltados para desenvolvedores. Ajude a desenvolver o software livre do mundo real na comunidade do developerWorks.
***
Sobre o autor: Shekhar Gulati é consultor Java na Xebia Índia. Ele tem seis anos de experiência corporativa em Java. Possui ampla experiência em projetos do portfólio Spring, como Spring, Spring-WS e Spring Roo. 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. 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.
***
Artigo original disponível em: http://www.ibm.com/developerworks/br/library/os-springroo5/index.html