segunda-feira, 10 de janeiro de 2011

Gerenciamento de Dependências com Maven - Parte 2

Neste post, será mostrada a view "Maven Repositories" do Eclipse, ilustrando algumas tarefas básicas, por exemplo, indexar um repositório para configurar / atualizar a busca de dependências pelo editor pom.xml do Eclipse.

A dinâmica do artigo será simular um projeto que utiliza usando Spring, JMS e ActiveMQ, para um projeto de mensageria. Durante os exercícios são sugeridas algumas dicas para selecionar as dependências corretas para o projeto.

Caso não tenha lido, a parte 1 desta série está disponível neste link.

Happy Maven!



Setup do Projeto - Dependências do Spring

Este exercício mostra como adicionar no projeto a dependência ao Spring Framework, uma poderosa biblioteca de Injeção de Dependências (uma excelente apostila sobre Spring pode ser acessada aqui).
  1. Crie um novo projeto Maven (se precisar de ajuda, leia este post).
  2. Clique no arquivo pom.xml, para abrir o editor do descritor do projeto.
  3. Na aba Dependencies, clique em Dependency / Add...
  4. Digite spring-context para adicionar esta dependência ao projeto. Verifique se o Eclipse sugeriu a versão desejada do Spring.
    1. Caso nenhuma sugestão seja mostrada, pode ser que nenhum repositório esteja habilitado, ou que os índices do repositório não tenham sido ainda inicializados. Esta situação é ilustrada na figura abaixo.
    2. Também pode ocorrer de o m2e não sugerir a versão desejada para a dependência. Além da reindexação, pode ser necessário configurar repositórios adicionais de pesquisa.


A view  "Maven Repositories" nos ajudará nesta tarefa. Através dela, é possível saber quais repositórios de dependências estão habilitados, bem como navegar pelos índices desses repositórios:


Note que esta view mostra
  • os artefatos presentes no repositório local (por padrão, o diretório USER_HOME/.m2/repositories)
  • os artefatos do workspace do Eclipse (neste caso, mostra o projeto jms que configuramos como projeto Maven com groupId:artifactId = projeto : projeto)
  • os repositórios globais, onde o repositório central do Maven é mostrado (configurados em USER_HOME/.m2/settings.xml). Note que seu índice está vazio, pois ainda não foi inicializado.
  • os repositórios do projeto, que estiverem configurados no pom.xml (veremos adiante).
Para saber mais sobre os tipos de repositórios, veja http://www.sonatype.com/books/m2eclipse-book/reference/eclipse-sect-repo-view.html.

A figura acima também é muito importante para entender um problema que o Maven resolve para o desenvolvedor: ele baixa automaticamente as bibliotecas e as organiza no diretório USER_HOME/.m2. Simples assim. E ele fará isso automaticamente para todo desenvolvedor que participar do projeto.

Na maioria dos projetos que não utiliza Maven ou algum outro gerenciador de dependências, o desenvolvedor tem que baixar as bibliotecas nos respectivos sites, selecionar os jars e configurá-los para que estejam no ClassPath da aplicação.

Este cenário, além de trabalhoso, é extremamente frágil. Basta que os desenvolvedores usem diferentes IDEs, ou diferentes sistemas operacionais, para inviabilizar o trabalho em equipe. Mesmo na mesma IDE, no mesmo sistema operacional, se o ClassPath da aplicação não estiver corretamente configurado na máquina de cada desenvolvedor, pode ser que a aplicação não funcione para todos no time.

Portanto, se você ainda não usa o Maven, pare de se torturar! Deixe o Maven gerenciar as dependências para vc e para o seu time!


Ao clicar com o botão direito no nome do repositório são mostradas as opções para habilitar o repositório e para indexá-lo. Para este artigo, optei pela opção "Minimum Index Enabled".

Após habilitado, a reindexação ocorre selecionando a opção "Rebuild Index".

Após a indexação, o repositório listará todas as bibliotecas que ele pode prover:


Neste momento, ao tentar adicionar a dependência spring-context, todas as opções (desde os releases mais recentes aos mais antigos) são disponibilizadas:


Similarmente, adicione a biblioteca spring-jms.


Ao salvar o arquivo pom.xml, o Maven baixa as dependências, o que pode ser visualizado no Console Maven do Eclipse:


Após esta operação, o Maven não só terá baixado as dependências, como configurado as dependências do Spring no Build Path do projeto.

Adicionando o ActiveMQ
Neste exercício, será adicionada a dependência ActiveMQ, e mostrar uma das principais armadilhas do uso incorreto do Maven: o de baixar dependências desnecessárias, devido a descuido na hora de selecionar corretamente as dependências.

PQP, o Maven faz backup da Internet no meu micro
Uma das críticas mais comuns que o Maven recebe é o fato de que, mesmo para projetos pequenos (neste momento ainda estamos com o projeto em branco!!!!) ele faz o download de muitos artefatos, antes que o desenvolvedor possa começar a trabalhar.

Isto pode ficar ainda pior, quando as dependências do projeto são mal configuradas, forçando o download de muitos artefatos que não são efetivamente necessários para o projeto. Isto é ruim tanto para os desenvolvedores - que são forçados a esperar o maven fazer downloads demorados após o primeiro checkout do projeto; e também para o build da aplicação, que além de mais demorado, tende a ficar muito maior do que o necessário.

Vamos entender agora porque isso acontece. O principal fator é que os repositórios públicos (como o Maven Central) estão abarrotados de artefatos, e nem sempre é fácil escolher qual o artefato adequado que deve ser utilizado (isto pode ser minimizado caso se decida gerenciar seus próprios repositórios em servidores locais, utilizando o Nexus, algo que poderá ser visto em artigos futuros).

Tomemos o ActiveMQ como exemplo. Veja a extensa lista de artefatos do grupo activemq que podem ser baixados:
Um desenvolvedor desavisado não perderá seu tempo analisando esta lista, e com certeza irá selecionar o primeiro item da mesma. Aí mora a primeira armadilha. Ao optar pela dependência "óbvia", o desenvolvedor acabará baixando mais artefatos do que ele efetivamente precisará, conforme pode ser visualizado na figura abaixo. Apenas para adicionar o ActiveMQ no projeto, foram baixados mais 40 jars!
Aqui nasce uma das maiores dificuldades de se usar o Maven: como escolher o artefato correto? A resposta pode ser difícil no começo, mas com o tempo, esta verificação tende a ficar mais natural.
  • Primeiramente fique atento às dependências Maven listadas no Package Explorer. Caso, ao adicionar uma dependência, muitos jars sejam adicionados (como na figura acima), isto é um mal sinal.
  • Orientações específicas podem ser encontradas nas documentações oficiais, wikis e foruns de cada biblioteca.
  • Quando o eclipse sugerir muitas opções para o mesmo artefato, seja paciente e analise as opções.
    • Evite artefatos com sufixo-all - eles normalmente contém muito mais jars do que o necessário para o projeto.
    • Procure os artefatos de sufixo -core, costumam conter apenas o essencial para a dependência pesquisada.
    • Fique atento à versão do artefato, para não baixar a dependência errada.
    • Consulte índices de repositório, por exemplo http://mvnrepository.com/https://repository.jboss.org/nexus/index.html e https://ebr.springsource.com.
    • Faça pesquisas no Google ou outro mecanismo de busca, para ver como outros desenvolvedores estão fazendo.

A dependência correta seria org.apache.activemq : activemq-core. Não só a quantidade de jars importados é bem menor, como se descobre que a versão anterior estava totalmente defasada (a versão atual é 5.4.2, enquanto que a que havia sido baixada inicialmente era 3.2.4).
Portanto, ao usar o Maven, selecione cuidadosamente os artefatos necessários para o projeto!

A segunda armadilha pode ser visualizada na figura acima: perceba que a dependência commons-logging foi adicionada duas vezes, uma pelo Spring (commons-logging-1.1.1), e outra pelo ActiveMQ (commons-logging-api-1.1). Isto é ruim não só por aumentar o tamanho do build, como também por adicionar o risco de adicionar exceções em runtime, caso as APIs das versões não sejam compatíveis entre si.

Para remover as duplicações, é necessário configurar exclusões. O processo é bem parecido com a adição de dependências: o Eclipse ajuda a pesquisar / selecionar a exclusão, através do editor pom.xml. Como sempre, selecione cuidadosamente os artefatos para fazer a exclusão correta.


Além de facilitar a configuração de dependências do projeto, o Maven dá de brinde duas facilidades: a aba Dependency Hierachy evidencia as relações hierárquicas entre os jars importados:

Já a aba Dependency Graph exibe estas relações na forma de um grafo:


Conclusão

Espero que as informações o tenha estimulado a adotar o Maven e as facilidades que ele oferece. O Maven é uma ferramenta poderosa que pode auxiliar e muito o setup de projetos em times de desenvolvimento. No entanto, é necessário utilizá-lo com cuidado e bastante atenção, para que erros grosseiros não degradem o ganho de produtividade que ele nos oferece.

O próximo artigo mostrará como utilizar JMS num container Spring, baseado no setup do projeto realizado neste post.

Nenhum comentário:

Postar um comentário