Michel Zanini

Blog sobre o framework Spring e tecnologias relacionadas

Maven 2 Reference Card

leave a comment »

O site DZone publicou um excelente cartão de referência sobre Maven 2. Maven é uma excelente ferramenta de build e gerenciamento de dependênicas. Vale a pena dar uma olhada.

10714

Abraços,

Michel Zanini.

Anúncios

Written by michelzanini

maio 28, 2009 at 6:40 pm

Publicado em Maven

10 dicas para melhorar seu desenvolvimento

leave a comment »

Hoje li este artigo e concordei com cada palavra. Os itens que dou mais destaque são estes:

  • 1 – Aprenda outra linguagem. Aprender uma outra linguagem é essencial para todo desenvolvedor. Na minha opinião, melhor ainda se for uma linguagem compilada, e uma linguagem dinâmica. Aprender ambas as filosofias irá ajudar o desenvolvedor a manter as coisas mais simples possíveis para resolver seu problema.
  • 5 – Este item é crucial. Já cansei de ver desenvolvedores abusando de padrões de projetos, OO e arquiteturas complexas. Quando alguém está aprendendo padrões é normal que comece a utilizar por tudo. O desenvolvedor experiente utiliza apenas onde realmente precisa, sem complicar o entendimento do código.
  • 8 – Outro item super importante. Uma das melhores maneiras de aprender como desenvolver bom código é olhando projetos open source que já o fazem. Portanto, tome o costume de olhar código fonte. Uma boa dica é o próprio framework Spring.

Abracos,

Michel Zanini.

Written by michelzanini

maio 27, 2009 at 10:35 am

Publicado em Boas práticas

AOP na prática: implementando um aspecto de auditoria

with 7 comments

No último artigo apresentei os conceitos básicos da Programação Orientada a Aspectos. Nesse artigo pretendo mostrar um exemplo prático de um problema muito comum em aplicações “enterprise”, a auditoria.

A auditoria é o processo de registrar todas as mudanças feitas pelos usuários para que se possa provar as ações tomadas por eles. Dessa forma é possível provar que o sistema não estava errado. Por exemplo, os dados sumiram porque alguém os excluiu.

Auditoria é uma responsabilidade “cross-cutting”, ou seja, se for programada de maneira tradicional estará espalhada por todo o sistema. Entretanto, é possível implementar tal funcionalidade utilizando técnicas de AOP, como veremos a seguir.

Dando continuidade ao artigo anterior, os exemplos estarão utilizando Spring e @AspectJ.

Exemplo Inicial

Começamos definindo uma interface geral para que nossos objetos de acesso ao banco de dados possam implementar, seguindo o padrão de projeto “Data Access Object”.

Utilizamos o recurso de tipos genéricos para que nossas implementações possam inserir qualquer tipo de objeto do domínio.

Para não complicar o exemplo a implementação da interface apenas imprimirá no console para sabermos que o método foi executado, porém imagine que poderíamos estar executando código JDBC ou Hibernate/JPA em seu lugar.

Agora implementaremos a primeira versão do nosso aspecto de auditoria, que simplesmente irá interceptar as execuções dos métodos inserir, atualizar e remover, imprimindo no console uma mensagem de aviso.

Note o uso do advice @AfterReturing para que o aspecto seja aplicado após uma execução com sucesso do método alvo. No pointcut interceptamos execuções de métodos de objetos que implementam a interface EntityDao, como a classe ConsoleClienteDao que criamos acima.

Para completar o exemplo mostramos o applicationContext.xml e o método Main para teste da aplicação.

A execução do método main irá imprimir o seguinte no console:

executou inserirCliente
depoisDeInserir
executou atualizarCliente
depoisDeAtualizar
executou removerCliente
depoisDeRemover

Agora, de posse de um exemplo muito simples, iremos melhora-lo para contemplar funcionalidades mais reais.

Auditando dados da entidade

Vamos criar uma superclasse abstrata para nossas entidades, dessa forma podemos utilizar o aspecto para obter informações de auditoria.

A classe Entity possui um id e um método a ser implementado pelas subclasses para obter uma String descritiva para auditoria. Em um sistema real poderíamos criar um POJO para substituir a String, de forma que ele poderia conter informações mais avançadas. Agora nossa classe Cliente passa a estender a classe Entity.

Para ter acesso aos dados da entidade que está sendo auditada podemos utilizar a expressão ‘args’ da sintaxe de pointcut do @AspectJ. Veja o exemplo abaixo.

Agora restringimos o método inserir a ter apenas um parâmetro, e do tipo Entity. Na expressão args(entity) definimos o nome do parâmetro, essa string deve coincidir com a variável declarada como parâmetro do método depoisDeInserir. Sendo assim, o objeto disponibilizado para o método é o mesmo passado como parâmetro do ConsoleClienteDao, e podemos utiliza-lo para auditoria.

Outra forma possível de auditar os dados da entidade seria utilizar a API de reflection para obter todas as suas propriedades, e então, montar uma descrição com a concatenação de seus valores.

Auditando mudanças nas atualizações

Em geral na auditoria, quando um objeto sofre um update, é desejável auditar as mudanças realizadas. Mas como podemos saber as mudanças feitas antes do update ocorrer? Podemos fazer um select antes e comparar os dados antes e depois da atualização.

Isso pode ser facilmente contemplado utilizando um advice @Around. Antes da execução do método atualizar fazemos um select e obtemos o objeto em seu estado atual, depois da atualização com sucesso, comparamos os dois objetos utilizando reflection (ou alguma interface), e então, auditamos o resultado.

Para manter os exemplos simples apenas comparamos os objetos com o método equals. Alem disso, nenhum tratamento foi feito para evitar NullPointerExceptions. Note que o método proceed executa o método alvo e em caso de exceções, será propagado para fora do aspecto, sem chegar a executar as ultimas linhas do método.

Filtrando quais classes participarão da auditoria

Imagine que para uma determinada aplicação é necessário fazer auditoria em apenas alguns DAO’s. Mas queremos que nosso aspecto continue consistente, ou seja, não sofra alterações constantemente. Para tal, uma idéia interessante é a utilização de anotações para marcar o pointcut do aspecto. Veja o exemplo abaixo.

Veja a expressão @target(exemplo.AptoParaAuditoria). Essa expressão significa que para o pointcut ser atingido a classe alvo tem que estar anotada com a anotação @AptoParaAuditoria. Dessa forma, a auditoria só ocorre quando desejado, nos DAO’s marcados com essa anotação. Também é possível criar filtros a nível de método utilizando a expressão @annotation(exemplo.AptoParaAuditoria).

Para melhorar o exemplo ainda é possível criar um atributo na anotação, uma enumeração, para informar em quais operações serão auditadas: inserir, atualizar, remover ou todas.

Obtendo informações do usuário corrente

Em um sistema de auditoria não basta saber o que foi feito e onde, também é necessário saber quem fez a alteração. Ou seja, é necessário obter dados do usuário logado. Em uma aplicação web isso se torna difícil, pois é impossível obter um objeto HttpRequest ou HttpSession de dentro do aspecto de auditoria.

Para essas situações existe uma técnica muito utilizada na AOP, associar recursos a Thread corrente. Assim é no Spring na área de controle de transações. Quando uma transação é aberta pelo aspecto de transação é associado a Thread corrente um java.sql.DataSource ou, no caso do Hibernate, uma org.hibernate.classic.Session. Dessa forma, ao longo da execução da Thread, de todos os lugares, é possível obter o mesmo recurso de conexão (na mesma transação), para executar o acesso ao banco de dados.

Essa solução pode ser aplicada nesse caso. Podemos implementar um filtro http (javax.servlet.Filer) que associa o request a Thread corrente. Dessa forma, de dentro do aspecto, podemos acessar o HttpRequest. Na verdade, o Spring já possui tal filtro implementando dentro do spring-web.jar, basta declararmos no web.xml.

Agora de dentro do aspecto de auditoria é possível acessar o request e a session desta forma:

Conclusão

A Programação Orientada a Aspectos é muito útil para funcionalidades como auditoria provendo sempre uma solução transparente. O Spring já nos traz vários recursos implementados que se utilizados de forma correta podem poupar muitos esforços. O @AspectJ está muito bem integrado com o Spring Framework, e o casamento das duas tecnologias pode trazer grandes benefícios.

Abraços,
Michel Zanini.

Written by michelzanini

setembro 22, 2008 at 1:42 am

Publicado em spring

Tagged with , ,

AOP utilizando @AspectJ e Spring

with 2 comments

Nesse artigo vou explicar os conceitos básicos de AOP e mostrar um exemplo inicial de como isso é feito utilizando @AspectJ 5 e Spring.

A Programação Orientada a Aspectos (AOP) complementa a programação orientada a objetos, provendo uma nova forma de pensar sobre a arquitetura da aplicação.

Na programação orientada a objetos encapsulamos as responsabilidades em classes. Já na AOP, as responsabilidades são encapsuladas em um aspecto. Um aspecto permite a modularização de interesses que geralmente aparecem espalhados por várias classes do sistema (denominados de interesses transversais – crosscutting concerns), como o gerenciamento de transações, por exemplo.

Veja a imagem abaixo. Se compreendermos as linhas horizontais como classes, veremos que os interesses de segurança, transação, etc. são transversais, ou seja, repetidos entre várias classes. A AOP contribui no sentido de retirar essas funcionalidades das classes e encapsula-las em aspectos, sem alterar o comportamento do sistema.

Conceitos

Aspect: é a unidade modular (funcionalidade) que encapsula interesses que atravessam vários objetos dentro do sistema.

Join Point: é um ponto durante a execução do programa que poderá ser afetado pelo aspecto. Um join point pode ser, por exemplo, a execução de um método do programa.

Point Cut: é uma expressão escrita em uma linguagem específica para a finalidade de selecionar join points (pontos de execução).

Advice: quando um join point é atingido, e selecionado pelo point cut, uma ação será executada. Essa ação é determinada advice.

Objeto Alvo: é o objeto que está sendo interceptado por um ou mais aspectos.

Proxy AOP: é o objeto criado pelo framework AOP para implementar a ligação entre o aspecto e o objeto alvo.

Veja na imagem abaixo. Durante a execução do programa, vários join points serão “atingidos”. No suporte a @AspectJ do Spring Framework (veremos exemplos a seguir) um join point é sempre a execução de um método. Dessa forma, imagine que cada um dos 6 join points abaixo representem 6 diferentes métodos. Um point cut é uma expressão, em linguagem específica, que seleciona quais dos 6 métodos (join points) serão afetados pelo aspecto. Nesse caso, imagine que os 3 joint points verdes foram atingidos pela expressão pointcut. O advice é a ação que irá executar quando eles foram atingidos, nesse caso, o advice será executado 3 vezes.

Tipos de Advice

No AspectJ existem 5 tipos diferentes de advice:

  • Before: ação do advice executa antes do join point.
  • After returning: ação do advice executa depois do joint ser executado com sucesso, ou seja, sem lançar exceção.
  • After throwing: ação do advice executa depois do joint ser executado com erro, ou seja, somente quando ele lançar uma exceção.
  • After (finally): ação do advice executa depois do joint ser executado independente de ter causado ou não exceção.
  • Around: advice que envolve a execução de um joint point. Com ele é possível codificar ações antes e depois do join point. Inclusive é possível alterar valores passados como parâmetro, como retorno, ou nem mesmo chamar o método do objeto alvo.

Exemplo concreto utilizando o suporte a @AspectJ com Spring

A partir da versão 2.0 do Spring Framework é suportado o uso do @AspectJ 5 de forma integrada ao seu container. Ainda é possível declarar aspectos por XML, como nas versões anteriores, porém agora é possível declarar aspectos com uso de anotações.

Para implementar um aspecto é necessário três coisas:

  • Colocar os jars ‘aspectjrt.jar’ e ‘aspecjtweaver.jar’ no classpath, juntamente com os jars tradicionais do Spring.
  • Declarar no applicationContext.xml o uso de aspectos com declaração por anotações, dessa forma:<aop:aspectj-autoproxy />.
  • Criar uma classe anotada com @Aspect para definir o aspecto. Utilizar uma anotação de advice (before, after ou around) e definir uma expressão point cut para selecionar quais joint points o aspecto afetará.

Veja um exemplo abaixo:

Repare que a expressão “execution(* xyz.abc.ClienteDao.*(..))” é o point cut e a anotação @Before é o advice. A linguagem do point cut é específica do @AspectJ e sua documentação pode ser encontrada no site da biblioteca. Explicando a expressão em detalhes:

  • execution: Qualquer execução de método.
  • Primeiro asterisco da expressão: que tenha qualquer visibilidade e retorne qualquer tipo de parâmetro.
  • xyz.abc: pacote que estão a(s) classe(s) que o point cut afetará.
  • ClienteDao: a classe afetada pelo point cut.
  • Segundo asterisco da expressão: qualquer método da classe ClienteDao.
  • (..): O método pode ter qualquer quantidade de parâmetros, de qualquer tipo.

Dessa forma podemos dizer que o método ‘realizarAcao’ será executado antes que qualquer método da classe ClienteDao executar.

É importante lembrar que o suporte à @AspectJ do Spring, como mostrado no exemplo, só selecionará join points que forem beans gerenciados pelo Spring. Ou seja, no exemplo acima o ‘ClienteDao’ tem que ser um bean no application context do Spring.

No próximo artigo veremos como implementar uma solução simples de auditoria utilizando AOP com Spring e @AspectJ.

Abraços,
Michel Zanini.

Written by michelzanini

agosto 28, 2008 at 2:53 am

Publicado em spring

Tagged with , ,

Customizando beans com BeanPostProcessor

leave a comment »

O container de injeção de dependências do Spring Framework foi criado para ser extensível. Tipicamente, não existe nenhuma razão para um desenvolvedor estender ou customizar alguma classe da hierarquia encabeçada pelas interfaces BeanFactory e ApplicationContext.

Um ponto muito utilizado para extensão da lógica de configuração do container IoC são os BeanPostProcessor’s. Essa interface dispõe de alguns métodos de “callback” que permitem customizar a lógica de instanciação e resolução de dependências. Se você precisa realizar algum trabalho logo após um componente (bean) ser instanciado, esse é um bom lugar para isso.

Um BeanPostProcessor é tratado de forma especial pelo container. Um bean desse tipo é instanciado antes de todos os outros. Quando um bean “convencional” for instanciado, os BeanPostProcessor’s configurados serão executados de acordo com a ordem definida.

A interface possuí dois métodos de callback.  Um dos métodos (postProcessBeforeInitialization) é executado antes de qualquer outro ponto de extensão (afterPropertiesSet ou init-method) e o outro (postProcessAfterInitialization)  é executado após o afterPropertiesSet e init-method. Veja na imagem abaixo para entender o ponto em que os métodos da interface BeanPostProcessor são chamadas (destaque em vermelho):

Agora vamos fazer um exemplo prático para entender melhor a idéia. Vamos implementar um BeanPostProcessor para fornecer um serviço de log para qualquer spring bean que necessite, de forma automática, sem necessidade de injeção.

Primeiro implementamos uma Interface chamada de LogAware com apenas um método disponível: setLog(org.apache.commons.logging.Log):

Agora vamos implementar o BeanPostProcessor que atua na inicialização dos objetos para injetar o log automaticamente em beans que implementam a interface acima:

Um bean que implementa a interface LogAware, como no exemplo abaixo, recebe a injeção do log automaticamente na fase de inicialização do objeto. Pois como o LogInjectingBeanPostProcessor foi declarado no applicationContext.xml, todas as instanciações de spring bean’s passarão por ele.

Veja logo abaixo o applicationContext.xml com os beans declarados. Repare que um BeanPostProcessor apenas precisa ser declarado no xml e é automaticamente registrado pelo Spring.

Agora vamos melhorar nosso exemplo para excluir a necessidade de uma interface a ser implementada, vamos substituí-la por uma anotação @Logger. Isso facilitará o desenvolvimento porém diminuirá um pouco a performance na inicialização do container. Veja a remodelagem do LogInjectingBeanPostProcessor para utilizar reflection e injetar o Log em um atributo que possui a anotação @Logger:

Agora o bean de exemplo ficou bem mais simples. Ele não implementa mais a interface, em troca disso utiliziamos a anotação. Na anotação é possível especificar uma string que será utilizada como nome do logger, caso nada for especificado, será utilizado o nome completo da classe.

Como vimos, um BeanPostProcessor pode adiantar muito a vida dos desenvolvedores trazendo um ponto
importante de customização e extensão. É claro que o exemplo dado não é muito útil. Existem maneiras mais simples de ter acesso a uma API de log. Porém a mesma idéia pode ser utilizada em vários outros casos.

Abraços.
Michel Zanini.

Written by michelzanini

agosto 13, 2008 at 3:53 am

Publicado em spring

Tagged with

Spring MVC

leave a comment »

Olá! Faz muitos dias que não escrevo aqui mas, vamos lá.

Encontrei esse excelente artigo sobre o framework web Spring MVC na InfoQ.

Para quem, como eu, não sabe ao certo qual framework web mais lhe agrada (ou desagrada) vale a pena dar um olhada. Em especial, no excelente trabalho feito pelo Spring MVC em facilidade de configuração e capacidade de assumir excelentes valores default.

Abraços,

Michel Zanini.

Written by michelzanini

agosto 13, 2008 at 12:42 am

Publicado em spring

Tagged with ,

Rod Johnson fala sobre EJB

leave a comment »

Trecho retirado de uma entrevista do Rod Johnson na InfoQ:

“I think with respect to EJB, I think my views are pretty well known on it. I mean EJB is just a bad technology. I can’t quite understand the desire that, at least Sun and some of the vendors seem to have to keep EJB alive. I think it has reached the point where it has a negative brand value. So for example a surprising number of large organizations like banks ban the use of EJB now. And realistically I think there were two choices: one was to either decide that maybe we should just end-of-life this, and the other was to accept that there was no point in backward compatibility with failed previous versions, and they start from scratch; that something obviously could be more successful without the baggage.”

Abraços.
Michel Zanini.

Written by michelzanini

junho 18, 2008 at 12:48 am

Publicado em Java

Tagged with