Como funciona a criação e manutenção da camada de persistência de uma aplicação desenvolvida com Roo?
Esse post demonstra como o Spring Roo configura a camada de persistência, descreve os comandos de persistência e como eles funcionam, além de esclarecer como o Spring Roo atua sob as entidades no decorrer do desenvolvimento. Esse texto complementa o conteúdo postado em Aventuras com Spring Roo no mundo real.
O Spring Roo é uma ferramenta RAD (Rapid Application Development) para desenvolvimento de aplicativos para Web, usando a linguagem Java. Se você nunca ouviu falar sobre o Spring Roo, leia Hello Roo.
Projeto demo
O exemplo usado como demonstração é bem simples, um CRUD de Produtos usando o HSQLDB, em poucos passos e sem burocracia o aplicativo poderá ser testado. Considerando que a instalação e configuração do Roo já foram concluídas, para criar o projeto basta executar no shell do Roo:
roo> project --topLevelPackage br.com.yaw.produtos
Configuração da persistência
O Roo resolve o mapeamento objeto relacional através da JPA, habilitamos o mecanismo de persistência através do comando persistence setup.
Atributos do comando persistence setup:
- database: indica qual é o Banco de Dados, as opções são MySQL, Oracle, DB2, PostgreSQL e outros.
- provider: o provedor JPA que será utilizado, as opções são: EclipseLink, OpenJPA e Data Nucleus.
- databaseName: indica o nome (instância) do banco de dados;
- userName e password: nome e senha do usuário de banco de dados;
- hostName: endereço da máquina com o banco de dados;
- jndiDataSource: indica o nome do DataSource armazenado no JNDI;
- persistenceUnit: nome da unidade persistência JPA (persistence.xml);
- applicationId: identificador o aplicativo no Google App Engine, caso o projeto venha a ser executado na infra-estrutura de Cloud do Google;
roo> persistence setup --database HYPERSONIC_IN_MEMORY --provider HIBERNATE
Com essa instrução o Roo altera e cria alguns arquivos de configuração. Veja:
- pom.xml: configura as dependências do Maven, isso inclui: API JPA, provedor JPA, driver do banco de dados, Spring ORM, Spring JDBC, Commons DBCP e Commons Pool.
- applicationContext.xml: adiciona as configurações de beans (do Spring) para DataSource, LocalContainerEntityManagerFactoryBean e ativa o Spring Transaction.
- persistence.xml: cria o arquivo com as configurações da JPA.
- database.properties: esse arquivo contém as configurações de conexão com o banco de dados.
Esses arquivos podem ser alterados diretamente em qualquer editor de texto a qualquer momento, sem o uso do Shell do Roo. Mas o Roo suporta alteração das propriedades através do comando properties set. A seguir um exemplo para mudar o nome do usuário do banco:
roo> properties set --path SRC_MAIN_RESOURCES --name /META-INF/spring/database.properties --key database.username --value teste
Outra forma de configurar propriedades do banco de dados é através do comando database properties set. O exemplo a seguir lista todas as propriedades contidas no arquivo database.properties:
roo> database properties list
O comando persistence setup pode ser executado a qualquer momento durante o desenvolvimento e quantas vezes necessário. Imagine a seguinte situação: no início de um projeto, como prova de conceito, o HSQLDB era uma opção interessante, mas no decorrer do projeto o restante da implementação deve ocorrer no MySQL.
Entidades
As entidades de domínio, Pojos que representam o modelo da aplicação, na verdade são a origem para geração de código no Spring Roo. A partir de uma entidade o Roo gera o Mapeamento Objeto Relacional e o código para os componentes Controller e View, seguindo o modelo Scaffold.
A seguir os comandos para criação da entidade Produto e dos campos Descrição e Preço. O mecanismo validação foi ativado através dos atributos notNull e min, o Spring Roo suporta a JSR 303.
roo> entity --class ~.model.Produto roo> field string descricao --notNull roo> field number --type java.lang.Double --fieldName preco --min 1
As entidades seguem o pattern ActiveRecord, onde cada entidade resolve o código CRUD para a tabela mapeada. Com o Spring Roo não usamos o pattern Data Access Object (DAO).
Mágica
A estratégia utilizada pelo Roo para implementar meta-programação em Java é através de Aspectos, com o AspectJ, popular implementação de AOP na plataforma Java. O código Java da classe Produto é extremamente pequeno, até os getters e setters são gerados por aspecto!
O Roo gera o arquivo Produto.java e demarcada a classe com 3 annotations e ainda gera 4 aspectos.
1. Produto_Roo_Entity.aj
Principal aspecto, define o ORM comum em todas as entidades, os atributos @Id e @Version. Esse aspecto implementa o código ActiveRecord com os métodos: persist, remove, flush e merge.
O aspecto implementa alguns métodos para consultas contra a base dados: findProduto, findAllProdutos, findProdutoEntries e countProdutos. Para não engessar a camada de persistência, esse aspecto também cria o método entityManager para expor o gestor de persistência fora do contexto de aspectos. Criado a partir da annotation @RooEntity.
2. Produto_Roo_Configurable.aj
Habilita a Injeção de Dependência do EntityManager via Spring IoC, através da annotation @Configurable.
3. Produto_Roo_JavaBean.aj
Esse aspecto cria o método get e o método set de cada atributo definido na entidade. Criado a partir da annotation @RooJavaBean.
4. Produto_Roo_ToString.aj
Gera o método toString concatenando os atributos em uma String. Criado a partir da annotation @RooToString.
Uma restrição importante do Roo: NUNCA manipule o código dos aspectos, afinal esse conteúdo é gerado pela ferramenta. A proposta do Roo é inferir o mínimo possível no código Java. O Roo demarca as classes com annotations e gera o código através de aspectos.
O driagrama acima ilustra como o Roo trabalha desde de a geração do código até a compilação da classe. O Roo monitora o arquivo Produto.java, qualquer modificação pode refletir nos aspectos, por fim o compilador AspectJ unifica o conteúdo dos aspectos com Java para gerar Produto.class.
Transação
No Roo o controle do escopo transacional com o banco de dados é realizado pelo Spring Transaction. Nas entidades, seguindo a linha Active Record, os métodos persist, remove, flush e merge são demarcados com a annotation @Transactional. Na camada Controller, gerada pelo Roo, esses métodos serão invocados em transações isoladas.
O desenvolvedor tem autonomia para aumentar o escopo transacional de uma requisição demarcando o método da Controller com @Transactional. Dessa forma todas as operações CRUD acionadas a partir desse método irão pertencer a mesma transação.
Em algumas situações pode fazer mais sentido criar um método na própria entidade para agrupar a execução de outros métodos na mesma transação, um exemplo disso poderia ocorrer no relacionamento master-detail. Basta marcar esse método com @Transactional, a única restrição é de que este método não pode ser static.
Terminando a demo
Para concluir e rodar a aplicação demonstração basta executar os seguintes comandos:
roo> controller all --package ~.web roo> perform package roo> quit $ mvn tomcat:run
Dica: os comandos executados no Shell do Roo ficam armazenados no arquivlo log.roo no diretório raiz da aplicação.
O Roo contém outros dois comandos que também envolvem a camada de persistência, finder e database reverser engineer. Mas deixo esses dois comandos para o próximo post!
Outras referências
- Posts do Spring Roo no Globalcoders;
- Documentação de referência do Spring Roo;
- Twitter do Roo;
[]s
Eder Magalhães
www.yaw.com.br
twitter.com/youandwe
twitter.com/edermag
Comentários