Por que eu devo ler este artigo:Este artigo apresenta motivações do porquê utilizar metadados em nossas aplicações e como podemos fazer uso deles em tempo de desenvolvimento e compilação para minimizar erros e aumentar a produtividade de nossos desenvolvedores.

Neste contexto encontra-se Annotation processors, uma ferramenta muito útil quando uma solução para validações e geração de artefatos e arquivos em tempo de compilação é necessária, fazendo com que estes processos tediosos e propensos a erros, quando executados manualmente, possam ser automatizados utilizando recursos nativos da plataforma Java.

O uso de metadados é bastante difundido atualmente no desenvolvimento de aplicações e pode ser definido como sendo a incorporação de informações adicionais a determinados artefatos de um sistema. Um exemplo disso seria a criação de uma entidade persistente em uma aplicação que faz uso de JPA, Hibernate ou qualquer outra ferramenta de mapeamento objeto-relacional.

Normalmente tem-se uma classe como qualquer outra, porém no momento que definimos em um XML ou através de anotações específicas que esta classe deve ser tratada como uma entidade persistente, esta classe passa a ser interpretada pela aplicação como algo diferente, e ter comportamentos adicionais.

Em outras palavras, a partir do momento que associamos informações adicionais a simples classes, elas passam a ser tratadas pela aplicação de forma diferenciada, e são estas informações adicionais que chamamos de metadados, ou metainformações (veja a Listagem 1).

O conceito de metadados já está presente há bastante tempo no processo de desenvolvimento de software. Além de adicionar comportamentos adicionais, metadados são utilizados também para configuração.

Originalmente estes dados eram comumente informados em arquivos externos, normalmente arquivos XML, ou também arquivos de propriedades, como .properties, .ini, etc. Porém, a definição destas informações em arquivos separados fazia, e ainda faz, com que os desenvolvedores não soubessem exatamente quais informações adicionais já tinham sido definidas para determinadas classes do sistema.

Isso acaba exigindo que conhecimento prévio de determinados arquivos de configuração seja pré-requisito para cada desenvolvedor, forçando a criação de documentação adicional para estas configurações.

Este tipo de abordagem faz com que soluções como J2EE, Hibernate, etc., tenham uma curva de aprendizado ainda mais alta, sem contar os problemas de deployment difíceis de depurar e corrigir, muitas vezes por motivos de simples erros em inúmeros arquivos de configuração.

Para resolver ou minimizar esta situação, projetos como o XDoclet foram criados. Estes frameworks foram extremamente importantes para a produtividade de vários desenvolvedores e projetos, pois com eles se tornava possível definir os metadados diretamente nas classes ou métodos que necessitavam de informações adicionais, fazendo com que estas informações fossem definidas de forma contextualizada, diretamente no elemento ao qual estavam relacionadas.

Isto foi possível através do uso de instruções especiais no Javadoc, os chamados doclets. A partir do uso de doclets específicos para J2EE, Hibernate, Spring, entre tantos outros projetos, o XDoclet fez com que nossas vidas fossem simplificada sem muito.

Listagem 1. Exemplo de mapeamento de classe persistente no Hibernate 2 utilizando XDoclet


    /**
   * @hibernate.class table = "NOTA_FISCAL" dynamic-update="true"
   * 
   * @hibernate.query name="NotaFiscal.findByNumeros"
   *   query="select notaFiscal
   *                  from NotaFiscal
   *                where notaFiscal.numero in (:numeros)"
   */
  public class NotaFiscal implements Serializable {
     private Integer numero;
   
     /* outras propriedades omitidas */
   
     /**
     * @hibernate.id generator-class="assigned" column ="N_INTERNO"
     */
     public Integer getNumero() {
        return numero;
     }
   
     /* outros getters/setters omitidos */
   
  }

Porém, o uso de Javadoc não resolvia todos os problemas e tinha algumas limitações. A principal delas era que estas informações continuavam sendo definidas fora do contexto da linguagem e consequentemente não havia uma forma padronizada de acessar este tipo de informação.

Além disso, como estes recursos não faziam parte da linguagem, era preciso que um processo adicional fosse incorporado no momento do empacotamento da aplicação e apenas neste momento é que alguns tipos de erros eram tratados e informados ao desenvolvedor.

Em alguns casos, plugins específicos foram criados para algumas IDEs, mas ainda assim não eram a solução ideal. Outro ponto negativo desse recurso é que as configurações acabavam se misturando à própria documentação das classes, o que em alguns casos dificultava o entendimento do que era documentação e o que era metadado de configuração, já que documentação em Javadoc não deixa de ser um tipo de metadado.

Porém, no final de 2004, o conceito de anotações foi introduzido no Java 5, através da JSR 175, A Metadata Facility for the Java Programming Language, o que fez com que metadados pudessem ser, enfim, definidos utilizando-se artefatos nativos da linguagem.

Anotações no Java 5

A aplicação de anotações em Java possibilita que metadados sejam adicionados a classes, propriedades e métodos fazendo uso diretamente de elementos nativos da linguagem, dentro do próprio código-fonte. Como estes metadados agora são parte integrante da sintaxe e API da plataforma Java, as anotações permitem coisas como:

· Informações extras para o compilador: as anotações podem ser processadas em tempo de compilação, possibilitando ao compilador executar validações e verificações adicionais;

· Processamento durante a compilação e deployment: é possível que estas anotações sejam inspecionadas e processadas em tempo de compilação e/ou deployment da aplicação. Isso permite a realização de verificações e/ou geração de artefatos adicionais, como classes e arquivos, que serão utilizados pela própria aplicação;

· Processamento em tempo de execução: as informações destas anotações também podem ser analisadas em tempo de execução, o que permite à aplicação responder de forma personalizada para cada tipo de anotação presente.

Além dos benefícios enumerados anteriormente, o uso de anotações faz com que no momento do desenvolvimento e principalmente durante a manutenção de um sistema, o desenvolvedor já tenha a capacidade de verificar se estes comportamentos adicionais estão presentes ou não, sem precisar conhecer outros detalhes da estrutura da aplicação. Um exemplo disso é a definição de uma entidade em JPA, fazendo uso de anotações ou via arquivo orm.xml, conforme demonstrado nas Listagens 2 e 3.

Listagem 2. Exemplo de configuração de inicialização do NetBeans no arquivo etc/netbeans.conf.


  @Entity
  @Table(name = "PESSOA")
  @NamedQueries({
      @NamedQuery(name = "Pessoa.findAll", query = "SELECT p FROM Pessoa p")})
  public class Pessoa implements Serializable { … }

Listagem 3. Exemplo utilizando XML de configuração.


  public class Pessoa implements Serializable { … }
   
  <?xml version="1.0" encoding="UTF-8"?>
  <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xs ... 

Quer ler esse conteúdo completo? Tenha acesso completo