Ainda
me lembro do inferno
das DLLs quando trabalhava mais ativamente com produtos da
Microsoft. Naquela época sofríamos com problemas de dependências. Quando
comecei a trabalhar com Java sofri o mesmo problema de uma forma um
pouco diferente, mas na essência era a mesma coisa.
Em java o problema tem o nome de inferno
dos jars. É incrível ver empresas que em 2010 ainda passam por
este tipo de problema em Java. Isto porque existem duas soluções que
resolvem este tipo de problema. Estou falando do Apache Maven 2 e do Apache Ivy. As suas soluções da
apache provêm a funcionalidade de gestão de dependências.
É comum ver uma pasta chamada *lib* no classpath das aplicações java com
mais de 100 jars, sendo que 70% ou mais não servem pra nada, nunca foi
usada, nunca se quer foi tocado pelo classloader e dificilmente ira ser
todado, mas por que as pessoas ainda fazem isso? Por dois motivos:
- Problemas de Dependências: Todo mundo já deve ter visto o famoso ClassNotFoundException várias vezes. Muitas vezes o que é feito é copiar todas as jars que
existem nos servidores de aplicação e que vêm nas distribuições dos
frameworks para a nossa boa e velha pasta lib. Claro que esta abordagem
não é a melhor, mas é muito utilizada e poupa mais tempo. O problema é
que você fica cheio de jars que você não precisa e a sua aplicação pode
inchar.
Nota: Os Servidores de aplicações mais robustos como o Websphere
por exemplo deixam você criar bibliotecas compartilhadas, assim você não
precisa empacotar todos os seus jars na sua distribuição(ear, war, jar)
e pode deixar o servidor colocar isso no classpath.
- Desconhecimento: É incrível o fato de que ainda existem muitas
empresas com baixo uso de maven ou ivy para resolução de dependências,
como consultor eu vejo isso muito e muito e não só no Brasil mas fora
também.
Usando
a gestão de dependências
Se você ainda não utiliza um
framework que faça gestão de dependências, recomendo começar a usar o
quanto antes. Pode ser maven 2 ou ivy, mas você deve usar, porque você
vai ganhar nos seguintes pontos:
- Dependências
Transitivas: Estas são as dependências das dependências e as que
realmente dão trabalho para achar. - Dependência certa, versão: Na abordagem da pasta lib, não
existe um controle em cima de qual versão do jar é necessário e se esta
versão esta em produção ou desenvolvimento, com um framework de
resolução de dependências você vai ter um controle fino sem enlouquecer
com este aspecto. - Download automático: Com uma solução de gestão de
dependências você precisar procurar, baixar e colocar o jar e as
dependências no classpath da sua aplicação. Esta é uma outra grande
vantagem. - Atualização de versões: Esta é outra grande dor de cabeça,
principalmente se você tem diversas aplicações que usam um jar que você
desenvolve internamente, logo pode ser necessário entrar em muitas
aplicações e fazer a troca da versão na mão, isso da trabalho e toma
tempo.
Espero que você já esteja convencido de que ter uma solução de
gestão de dependências como ivy e maven é uma boa idéia. Às vezes as
empresas usam maven ou ivy mas esquecem de ter uma solução de
repositório corporativo por traz disso tudo.
Construindo um repositório corporativo com artifactory
Eu já usei em produção soluções de
repositório corporativo para java como o nexus e archiva. Mas hoje em
dia uso o Artifactory e
não me arrependo disso. O problema principal do archiva é que ele é
muito lento pare baixar e resolver as dependências, coisa que o
artifactory faz muito bem e muito rápido.
Você deve usar o artifactory por
que ele prove um console web para que você administre os seus
jars (soluções e plugins) de terceiros como spring, hibernate, jboss e os
que você faz na sua própria empresa. Esta separação pode ser feita
através de repositórios.
Também é possível separar e
controlar as versões do que está em desenvolvimento e do que está em
produção. Muitas vezes as pessoas enxergam o artifactory apenas como
uma solução de proxy, evitando que você gaste banda da sua empresa, mas
na verdade é muito mais.
Controle das dependências
Com o artifactory você pode
controlar através de usuários e grupos, quem e que aplicação pode
consumir e usar determinados repositórios e jars. Da forma que você pode
restringir o uso de Spring por exemplo apenas para alguns projetos (eu
não faria isso), você também passa a controlar melhor as suas
dependências internas, das soluções que você faz, limitando e
centralizado a forma de acesso a essas dependências, de forma que você
nunca mais vai perder uma.
Repositório consolidade em M2 e
Ivy
A figura acima mostra que
através de um repositório *virtual* no artifactory você pode servir a
consumidores com maven ou com ant usando ivy. O que é mais legal disso
tudo é que o repositório é o mesmo.
Como isso é possível? Porque o
artifactory é flexível e vamos seguir alguns padrões para fazer
isso. O Artifactory já trabalha com o padrão de dependências do maven
2, que é:
- GroupID: Grupo da solução, agrupador macro
de módulo ou empresa provedora. Ex: org.springframework. - ArtifactID: Representa o identificar do artefato em si que
está sendo disponibilizado/consumido. Vai ser muitas vezes o nome do jar
da antiga pasta lib como por exemplo: spring. - Version: É a versão do jar. No maven, quando vemos algo do
tipo 1.0 normalmente indica que a solução está em produção ou se foi
disponibilizada usa-se GA. Quando a solução esta em desenvolvimento se
utiliza SNAPSHOT e as vezes seguido da data e hora do último build.
Com ivy, as coisas funcionam de forma parecida, pois temos os
atributos organisation, module e revision, que tem equivalência em ordem
a groupid, artifactid e version. A grande diferença é que com ivy nos
passamos um pattern estilo regex para a resolução de dependências. Este
tipo de coisa não ocorre no maven porque o pattern é o mesmo e
pré-definido.
Fato é que o ivy lhe dá mais flexibilidade, mas também faz você passar
muito mais trabalho. O que sugiro é que você use o mesmo pattern do
maven no ivy, assim terá consistência nos deploys feitos no
artifactory e, desta forma, terá o mesmo repositório para ivy e
maven.
Configurando i Ivy para para baixar e fazer deploy no Artifactory
Para fazer isso basta utilizar o
arquivos xml abaixo que chamei de ivy-artifactory-settings.xml;
<ivysettings>
<settings defaultResolver="public"/>
<credentials
realm="Artifactory Realm"
host="seu_host_do_artifactory"
username="admin_user"
passwd="admin_password"
/>
<resolvers>
<ibiblio name="public" m2compatible="true" root="http://seu_server:8080/artifactory/seu_proxy_repository" />
<url name="publish_artifactory" m2compatible="true" >
<artifact pattern="http://seu_server:8080/artifactory/seu_repositorio_release_repository/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
</resolvers>
</ivysettings>
Não se esqueça de usar o pattern
[organisation]/[module]/[revision]/[type]s/[artifact].[ext] para
resolver as dependências. Na hora em que você for publicar o seu jar via
ivy, você pode usar uma task para fazer o pom do maven a partir das
dependências do ivy, seria algo mais ou menos assim:
<ivy-makepom
ivyfile="${ivy.xml.file}"
pomfile="${basedir}/dist/${ivy.organisation}/${ivy.module}/${ivy.revision}/${ivy.module}-${ivy.revision}.pom"
>
<mapping conf="default" scope="compile" />
<mapping conf="runtime" scope="runtime" /> </p> </ivy-makepom>
Levando em conta que você gerou seu
jar na pasta dist e que ele segue o pattern do maven 2, ou seja, está dentro da pasta com a organização, depois a pasta do módulo, a pasta da
versão e o jar com a versão.
Se você quiser saber como consumir e publicar os artefatos via maven, não terá
problema nenhum, pois o ivy agora segue o mesmo pattern do maven, então um
pode consumir dependências geradas pelo outro.
Desta forma não importa se o
projeto usa maven 2 ou ant com ivy, usando o artifactory com os
padrões e dicas que dei neste artigo você terá o mesmo repositório para
tudo.
Abraços e até a próxima.