Você está na página 1de 53

Explicação

Downloads
Caso queira usar o IVY imediatamente a partir desse vídeo, pode baixar o projeto aqui. O
projeto deve ser importado no Eclipse.

Introdução ao IVY
ANT como ferramenta de construção de software ajuda muito na automatização de tarefas
comuns no build de software. Quando construímos uma aplicação também importa saber
componentes usaremos e suas versões. No mundo Java esses componentes são as
bibliotecas, ou seja, as dependências da aplicação. A aplicação só funciona com esses
componentes em uma versão específica. Isso significa que o desenvolvedor precisa se
preocupar com as dependências.

O IVY é uma ferramenta que ajuda no gerenciamento das dependências e seu uso com
ANT é muito simples. Para um projeto que já utiliza ANT como ferramenta de build o IVY
pode ser facilmente integrado. Vamos configurar ANT com IVY e usar tarefas no ANT para
resolver as dependências do projeto.

O gerenciamento de dependências manual ocorre quando o próprio desenvolvedor acessa


o site da biblioteca, baixa uma versão e a adiciona no classpath da aplicação. Além disso
ser muito trabalhoso, nem sempre é fácil saber qual versão da dependência é necessária e
onde encontrá-la.

Por exemplo, um projeto define a dependência hibernate-core na versão 3.3.4. Com


certeza o Hibernate utiliza outras bibliotecas, possuindo suas próprias dependências.
Essas são as dependências transitivas (ou dependências de dependências). Como
desenvolvedores não queremos nos preocupar em saber, por exemplo, qual versão do
commons-collections o Hibernate usa. O gerenciador de dependência deve resolver isso
e assumir a responsabilidade de cuidar das dependências transitivas.

Com IVY podemos usar uma tarefa no ANT que automatiza esses passos. Isso deve ser
tão fácil de usar quanto compilar ou empacotar o projeto, ou seja, apenas uma chamada
no IDE ou na linha de comando. O IVY deve verificar e atualizar as dependências do
projeto e avisar quando há conflitos entre JARs.

Encontrando as dependências
Para o primeiro exemplo, vamos definir as dependências de uma aplicação web que
pretende usar Spring MVC como controlador MVC. Como já foi dito, o IVY baixará as
dependências automaticamente, mas de onde ele as baixará?

Existem servidores na internet com a tarefa de fornecer JARs para aplicações. Esses
servidores, ou melhor repositórios, foram criados para serem utilizados com outra
ferramenta de construção de software, o Maven. O IVY utiliza os mesmos repositórios do
Maven, aproveitando a ampla infraestrutura já existente.
Existem vários repositórios na internet. Um lugar central para pesquisar pelos artefatos é o
site http://mvnrepository.com.

Procurando pelo "spring mvc" no http://mvnrepository.com vamos encontrar o registro do


framework spring-mvc. Nesse link podemos encontrar todas as versões disponíveis dentro
do repositório.
Seguindo um link de uma versão aparecem mais detalhes sobre aquela dependência (ou
artefato - segundo o Maven). Nessa página, escolhendo a aba IVY, encontramos a
configuração para o arquivo ivy.xml que é utilizado para configurar as dependências do
nosso projeto, por exemplo:

<dependency org="org.springframework" name="spring-webmvc"


rev="3.1.0.RELEASE"/>

Na mesma página também estão listados os artefatos do Spring MVC, ou seja


dependências desse framework. São essas as dependências transitivas.
Para ver mais detalhes sobre a versão 3.1.0 do Spring MVC acesse o site do repositório:
spring-webmvc-3.1.0

Declaração das dependências


A configuração das dependências com IVY não costuma ser feita dentro do build.xml. O
IVY possui um arquivo XML separado, o ivy.xml. Esse arquivo descreve um módulo e
possui, além de algumas informações genéricas sobre o projeto, a definição das
dependências.

A tag obrigatória info define a organização ou empresa (br.com.caelum) e nomeia o


módulo, normalmente o nome da aplicação (aqui agenda). Após essas tags, seguem as
dependências da aplicação. No exemplo abaixo há apenas uma. O módulo depende do
framework spring-mvc na versão 3.1.0 que copiamos do site http://mvnrepository.com:

<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-


instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info organisation="br.com.caelum" module="agenda" />

<dependencies>
<dependency org="org.springframework" name="spring-webmvc"
rev="3.1.0.RELEASE" conf="default" />
</dependencies>

</ivy-module>

Task para resolver os JARs


Com as dependências definidas no ivy.xml, podemos utilizar as tarefas do IVY dentro do
build.xml para baixá-las automaticamente. Vamos definir um target para resolver as
dependências usando a tarefa específica do IVY ivy:retrieve:

<project name="agenda" xmlns:ivy="antlib:org.apache.ivy.ant">


...
<target name="atualiza-dependencias" description="resolver as
dependencias do projeto">
<ivy:retrieve />
</target>
...
</project>

Repare que foi preciso definir um namespace xmlns:ivy= na declaração do projeto.

Para o ANT achar a tarefa é preciso ter o JAR do IVY no classpath. O JAR vem da
distribuição do Apache IVY e pode ser baixado no site do projeto: http://ant.apache.org/ivy/
Então podemos disponibilizar o JAR do IVY (por exemplo ivy-2.2.0.jar) no classpath do
ANT. No final é o ANT que vai usar IVY. Para adicionar o IVY no classpath podemos
configurar o classpath pelo comando ant com o argumento -lib, por exemplo:

ant -lib ivy-2.2.0.jar

Alternativamente podemos declarar uma tag path com a biblioteca do IVY e definir na task
no build.xml. Essa maneira tem a vantagem de não precisarmos lembrar de passar o
JAR do IVY na linha de comando:

<path id="ivy.lib.path">
<fileset dir="ivy-lib" includes="*.jar"/>
</path>

<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>

Pronto, a integração do ANT e IVY está feita. Foi preciso definir o classpath (JAR do IVY
na pasta lib), declarar o namespace e usar a tarefa do IVY (ivy:retrieve) dentro do
build.xml.

O arquivo iyy.xml deve estar na mesma pasta do build.xml. Assim podemos executar o
target ant atualiza-dependencias gerando o seguinte resultado:

atualiza-dependencias:
[ivy:retrieve] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: url = jar:file:/usr/share/ant/lib/ivy-
2.2.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies ::
br.com.caelum#agenda;working@nico-vaio
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.springframework#spring-webmvc;3.1.0.RELEASE in
public
[ivy:retrieve] [3.1.0.RELEASE] org.springframework#spring-
webmvc;3.1.0.RELEASE
....
[ivy:retrieve] downloading
http://repo1.maven.org/maven2/org/springframework/spring-webmvc/3.1.0.RELEASE
/spring-webmvc-3.1.0.RELEASE.jar ...
[ivy:retrieve] ..............................................................
.............

....

[ivy:retrieve] [SUCCESSFUL ] org.springframework#spring-


aop;3.1.0.RELEASE!spring-aop.jar (3171ms)
[ivy:retrieve] :: resolution report :: resolve 31969ms :: artifacts dl
152590ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 11 | 9 | 9 | 0 || 11 | 9 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 11 artifacts copied, 0 already retrieved (3066kB/36ms)

A mensagem pode variar e na primeira execução demorar.

Cache do Ivy
A segunda execução será muito mais rápido. Mas por quê? O que acontece é que o IVY
baixa os JARs do repositório, colocando-os dentro da pasta lib do projeto. Mas além de
colocar as bibliotecas na pasta lib o IVY guarda os JARs em uma pasta independente do
projeto. Normalmente essa pasta se encontra na raiz da pasta do usuário e se chama
.ivy2:
/pastaDoUsuario/.ivy/cache/....

Na segunda execução os JARs vêm da pasta .ivy2 e só serão copiadas localmente. No


nosso exemplo, uma única dependência spring-mvc o IVY colocou 11 JARs dentro da
pasta lib:

- aopalliance.jar
- commons-logging.jar
- spring-asm.jar
- spring-aop.jar
- spring-beans.jar
- spring-context.jar
- spring-context-support.jar
- spring-core.jar
- spring-expression.jar
- spring-web.jar
- spring-webmvc.jar

Resumo
Vimos como integrar o IVY com ANT, usando a tarefa ivy:retrieve. Como o IVY
aproveita os mesmo repositório do Maven podemos procurar as dependências dentro
desses repositórios. Para a configuração das dependências usamos um arquivo especifico
do IVY, o ivy.xml.

Atividade 1 de 8
Como se chama o arquivo do Ivy para configurar as dependências?

17/12/2013 10:24

ivy.properties

ivy-deps.properties

deps.xml

ivy.properties.xml

ivy-properties.xml


ivy.xml

ivy-deps.xml

Atividade 2 de 8
Onde o Ivy procura as dependências por padrão?

17/12/2013 10:25

Ivy mantem seu proprio repositorio no site do framework.

Ivy acessa cada site da biblioteca e baixa os JARs.

Dentro de um repositorio, em uma pasta na maquina local.

Dentro de um repositorio, por padrão é utilizado o repositório do Maven.

Atividade 3 de 8
Como configurar o ANT para usar as tarefas do Ivy?

17/12/2013 10:25

O JAR do Ivy deve estar dentro do classpath E o namespace do Ivy deve estar
definido.


Basta definir no classpath o JAR do Ivy.

Basta declarar o namespace para usar as tarefas do Ivy.

Atividade 4 de 8
Como se chama a tarefa do Ivy para baixar e adicionar as dependências no projeto?

17/12/2013 10:25

restore

download

retrieve

define

Atividade 5 de 8
Como se chama a pasta que o Ivy usa para colocar as dependências no projeto?

17/12/2013 10:26

jars


lib

target

deps

Atividade 5 de 8
Como se chama a pasta que o Ivy usa para colocar as dependências no projeto?

17/12/2013 10:26

jars

lib

target

deps

Atividade 7 de 8
Acesse o http://mvnrepository.com. Procure pela dependências hibernate-core e escolhe
a versão 4.1.1.FINAL. Cole a declaração do Ivy aqui:

Atividade 8 de 8
A empresa DRLN (nome fictício, site fictício: http://drln.com.br) está desenvolvendo uma
aplicação web com Spring MVC na versão 3.1.0 para administrar tarefas dos funcionários.
O nome do projeto é drln-tarefas. Crie o ivy.xml e build.xml para carregar as
dependências.

Explicação

Apresentação da aplicação Web


Vamos continuar resolvendo dependências com Apache Ivy, mas para este aula
focaremos nas dependências de uma aplicação Web. Ela terá dois tipos (escopos) de
dependências. O primeiro são as dependências para rodar e compilar as classes de
aplicação, o segundo são as dependências para compilar e rodar os testes. Veremos que
será possível gerenciar esses dois tipos de dependências confortavelmente com Ivy.

Nossa aplicação web agenda de exemplo foi estruturada da seguinte maneira: uma pasta
src com pacotes para controladores, modelo e outro para DAO's e uma pasta src-teste
com as nossas classes de testes.

As dependências da aplicação também foram definidas: os JAR's da aplicação na pasta


WEB-INF/lib e os JAR's na pasta lib-teste para rodar o junit. Por último, o JAR do Ivy na
pasta ivy-lib.

Temos o arquivo ivy.xml com o elemento info e depedencies preparados, mas ainda
sem dependências concretas.

<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-


instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info module="agenda" organisation="br.com.caelum" />

<dependencies>
</dependencies>

</ivy-module>

Temos também o build.xml com o namespace definido na declaração do elemento


project, o caminho definido para encontrar o JAR, a tarefa definida através do elemento
taskdef e também o target do ANT para realmente carregar as bibliotecas.

<project name="agenda" xmlns:ivy="antlib:org.apache.ivy.ant"


default="atualiza-dependencias">

<path id="ivy.lib.path">
<fileset dir="ivy-lib" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>

<target name="limpar" >


<delete dir="lib" />
<mkdir dir="lib" />
</target>

<target name="atualiza-dependencias" depends="limpar">


<ivy:retrieve />
</target>

</project>

Dependências da aplicação Web


A primeira coisa que precisamos fazer é definir as dependências do projeto web que são
compostos de: Spring MVC, Driver MySQL e JSTL. Recorreremos aos repositórios do
Maven para obtermos essas dependências.

Em mvnrepository.com, após encontrar o Spring MVC mais recente, copiamos a


declaração da dependência do Ivy para o arquivo ivy.xml. O próximo passo é resolver as
dependências do driver do MySQL e do JSTL.

Segue ivy.xml com a definição das dependências:

<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-


instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info module="agenda" organisation="br.com.caelum" />

<dependencies>
<dependency org="org.springframework" name="spring-webmvc"
rev="3.1.0.RELEASE" />
<dependency org="mysql" name="mysql-connector-java" rev="5.1.18" />
<dependency org="jstl" name="jstl" rev="1.2" />
</dependencies>

</ivy-module>
Para cada dependência queremos que o IVY carregue apenas o JAR's (dependência e
dependências transitivas) e nenhuma dependência opcional, nem o javadoc ou código
fonte, por isso adicionaremos a configuração default para cada dependência.

<dependencies>
<dependency org="org.springframework" name="spring-webmvc"
rev="3.1.0.RELEASE" conf="default"/>
<dependency org="mysql" name="mysql-connector-java" rev="5.1.18"
conf="default"/>
<dependency org="jstl" name="jstl" rev="1.2" conf="default"/>
</dependencies>

Executando o ANT na linha de comando, ant atualiza-dependencias, o output gerado


pelo IVY mostra que 13 artefatos (no nosso casos JARs) foram baixados:

atualiza-dependencias:
[ivy:retrieve] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: url =
jar:file:/Users/caelum/Documents/IVY/IVY-workspace/agenda/ivy-lib/ivy-
2.2.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies ::
br.com.caelum#agenda;working@MacBook-Pro-de-Caelum.local
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.springframework#spring-webmvc;3.1.0.RELEASE in
public
[ivy:retrieve] found org.springframework#spring-asm;3.1.0.RELEASE in
public
[ivy:retrieve] found org.springframework#spring-beans;3.1.0.RELEASE in
public
[ivy:retrieve] found org.springframework#spring-core;3.1.0.RELEASE in
public
[ivy:retrieve] found commons-logging#commons-logging;1.1.1 in public
[ivy:retrieve] found org.springframework#spring-context;3.1.0.RELEASE in
public
[ivy:retrieve] found org.springframework#spring-aop;3.1.0.RELEASE in
public
[ivy:retrieve] found aopalliance#aopalliance;1.0 in public
[ivy:retrieve] found org.springframework#spring-expression;3.1.0.RELEASE
in public
[ivy:retrieve] found org.springframework#spring-context-
support;3.1.0.RELEASE in public
[ivy:retrieve] found org.springframework#spring-web;3.1.0.RELEASE in
public
[ivy:retrieve] found mysql#mysql-connector-java;5.1.18 in public
[ivy:retrieve] found jstl#jstl;1.2 in public
[ivy:retrieve] :: resolution report :: resolve 730ms :: artifacts dl 12ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 13 | 0 | 0 | 0 || 13 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 13 artifacts copied, 0 already retrieved (4796kB/108ms)

No projeto, vimos que o IVY criou a pasta lib com os 13 JARs baixados, mas os mesmos
JARs já estavam na pasta WEB-INF/lib para que fosse possível compilar e rodar a
aplicação.

Definição do local das


dependências
Claro que não queremos repetir os JARs, por isso vamos configurar um pattern para
ensinar o Ivy que as bibliotecas baixadas devem ser gravadas na pasta WEB-INF/lib.

A tarefa ivy:retrieve recebe um parâmetro pattern. Podemos passar o parâmetro


artifact, que indica o nome do arquivo e ext a extensão. Vamos apagar a pasta lib
baixada anteriormente e os jars da pasta WEB-INF/lib, o target fica como:

<target name="atualiza-dependencias" >


<ivy:retrieve pattern="WebContent/WEB-INF/lib/[artifact].[ext]" />
</target>

Ao executar ant atualiza-dependencias e depois atualizando o eclipse é percebido que


na pasta apareceram todos os JAR's dentro da pasta definida pela pattern. Podemos
perceber que não apareceram as versões dos JAR's.

No pattern podemos também adicionar o revision para aparecer a versão do JAR:

<target name="atualiza-dependencias" >


<ivy:retrieve pattern="WebContent/WEB-INF/lib/[artifact]-[revision].
[ext]" />
</target>

Portando temos mais um problema: os JAR's do junit. Quem deve resolver é o IVY, então
vamos procurar pelo junit no repositório do maven para pegar a versão mais nova:

<dependency org="junit" name="junit" rev="4.10" conf="default"/>


Vamos copiar a definição da dependência e colar no ivy.xml dentro do projeto pedindo
para carregar apenas o padrão e nenhuma configuação (conf="default").

Com a nova dependência vamos testar na linha de comando com ANT executando o
comando: ant atualiza-dependencias:

.....
[ivy:retrieve] found junit#junit;4.10 in public
[ivy:retrieve] found org.hamcrest#hamcrest-core#jstl;1.1 in public
....
[ivy:retrieve] :: resolution report :: resolve 731ms :: artifacts dl 17ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 15 | 0 | 0 | 0 || 15 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 15 artifacts copied, 13 already retrieved (322kB/46ms)

Carregou o junit, mas a biblioteca foi colocado pelo o IVY dentro da pasta WebContent. Os
JAR's do junit devem fazer parte da pasta WEB-INF/lib. Podemos então apagar esses
dois jars.

Separando dependências através


de configurações
O que precisamos fazer agora e a separação das dependências, para isso existe o
elemento configurations. É possível definir a minha própria configuração, por exemplo,
para as bibliotecas da minha aplicação web e também para as bibliotecas que precisamos
para rodar os testes. Isso nos possibilita associar uma dependência com a minha própria
configuração:
<configurations>
<conf name="webapp" />
<conf name="teste" />
</configurations>

E agora associar com as dependências, por exemplo:

<dependencies>
<dependency org="junit" name="junit" rev="1.4" conf="teste->default" />
<dependency org="org.springframework" name="spring-mvc"
rev="3.1.0.RELEASE" conf="webapp->default" />
.....
</dependencies>

Assim a configuração teste foi mapeado (->) para default default para aquele
dependência, wepapp carregara tudo que é default.

Aplicando configurações no
build
Voltando ao nosso build.xml, na tag ivy:retrieve vamos aplicar as configurações
webapp e teste no para associar a tarefa com a configuração, ou seja no final com um
grupo de dependências.

Rodando mais uma vez na linha de comando o ANT: ant atualiza-dependencias vemos
que DOIS relatórios foram gerados: uma para a configuração webapp e outro para teste:

---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| webap | 13 | 0 | 0 | 0 || 13 | 0 |
---------------------------------------------------------------------
.....
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| teste | 2 | 0 | 0 | 0 || 2 | 0 |
---------------------------------------------------------------------

No nosso projeto vemos que a pasta lib-teste contem os JARs do junit.

Mais mapeamentos e resumo


Em nosso ivy.xml vamos declarar as configurações (por exemplo webapp) e as
dependencias (por exemplo Spring MVC). A configuração é apenas um nome para indicar
a finalidade das dependências. A nossa configuração foi mapeada (->) para alguma
configuração dessa dependência, por exemplo, default:
<dependency org="org.springframework" name="spring-webmvc"
rev="3.1.1.RELEASE" conf="webapp->default"/>
Existem outras opções para default. Poderíamos indicar apenas as dependencias para
compilação e mapear webapp->compile, ou para rodar a aplicação (webapp->runtime), ou
master indicando apenas o jar principal sem as dependências transitivas.

Outras opções seriam:

 optional - o jar principal, todas dependencias transitivas e também os opcionais.


 provided - são dependências que o conteiner fornece.

Além dessas opções que definem a abrangência podemos querer carregar o código fonte
também (sources), ou a documentação javadoc. É possível realizar combinações, por
exemplo:

webapp->master, sources
webapp->compile, javadoc
teste->*

No exemplo acima, webapp foi mapeado para master e sources. Isso significa que
queremos carregar o jar principal apenas e o código fonte dessa dependência.

No build.xml definimos a tarefa para carregar, o ivy:retrive. Ela realmente carrega


essas dependências definidas no ivy.xml. Na tarefa associamos qual configuração
queremos carregar e qual é o pattern (caminho de pasta e nomenclature dos JARs).

<ivy:retrieve pattern="/[config]/[type]/[artifiact]-[revision].[ext]"
conf="webapp" />

Nesse caso, o pattern é composto pelo config (ou seja webapp), o type (por exemplo jar
ou javadoc). artifact é o nome da dependência (spring-webmvc) e revision e a versão,
além da e a extensão do artifato (jar normalmente).

Atividade 1 de 5
Às vezes, para uma determinada dependência, queremos que o Ivy carregue apenas os
JARs e nenhuma dependência opcional. Para isso, podemos passar como parâmetro o
valor default em um determinado atributo do elemento dependency. Que atributo é esse?

17/12/2013 10:27

branch

conf


name

transitive

Atividade 1 de 5
Às vezes, para uma determinada dependência, queremos que o Ivy carregue apenas os
JARs e nenhuma dependência opcional. Para isso, podemos passar como parâmetro o
valor default em um determinado atributo do elemento dependency. Que atributo é esse?

17/12/2013 10:27

branch

conf

name

transitive

Atividade 3 de 5
Para organizarmos melhor nossa aplicação queremos separar as bibliotecas necessárias
para rodar a aplicação web das bibliotecas para executar os testes, ambos em
configurações diferentes.

Altere o ivy.xml para mapear essas dependências para que as bibliotecas do JUnit
fiquem defindas em teste->default e as bibliotecas do Spring fiquem em webapp-
>default:

Atividade 4 de 5
Criamos duas configurações webapp e teste no exercício anterior. Com este mapeamento
já feito queremos agora separar as bibliotecas em pastas diferentes.

Altere a tarefa ivy:retrieve no build.xml para que as JARs da configuração teste


fiquem no diretório /teste/jar/nomedojar-revision.jar e as JARs de da configuração
webapp no diretório /webapp/jar/nomedojar-revision.jar .

Segue um esboço do build.xml. Dentro da target adicione as tarefas do Ivy:

Atividade 5 de 5
Na nossa aplicação já se encontra um ivy.xml. Nele declaramos uma configuração
runtime que foi mapeado para default. Com ela carregaremos o JAR principal do
Hibernate e todas as dependências transitivas.

Para esse exercício altere a configuração da dependência para carregar apenas o JAR
principal E o código fonte. Cole o XML da definição da dependência abaixo.

Explicação

Lidando com conflitos


Neste capítulo gerenciaremos duas dependências principais. A primeira, o Hibernate e a
segunda uma implementação do JSF da Apache, o MyFaces. É claro que essas duas
dependências terão dependências transitivas. Veremos como gerenciar essas
dependências transitivas e o que fazer quando houver um conflito entre essas duas
dependências.

Temos no nosso projeto inicial preparado no Eclipse com um build.xml e com um


ivy.xml. Dentro do build.xml temos um target para limpar a pasta lib com nossas
dependências e um target para atualizar essas dependências que usa a tarefa
ivy:retrieve.

<project name="agenda" xmlns:ivy="antlib:org.apache.ivy.ant"


default="atualiza-dependencias">

<path id="ivy.lib.path">
<fileset dir="ivy-lib" includes="*.jar"/>
</path>

<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>

<target name="limpar" >


<delete dir="lib" />
<mkdir dir="lib" />
<mkdir dir="report" />
</target>

<target name="atualiza-dependencias" depends="limpar">


<ivy:retrieve />
</target>
</project>

ivy:retrieve realmente carregará as dependências, por isso já temos a tarefa declarada


através do taskdef, além do caminho para encontrar a biblioteca do Ivy: o ivy.jar.

No ivy.xml temos o elemento info e o elemento dependencies. Vamos declarar a


dependência do Hibernate, procurando no repositorio do Maven por Hibernate. Usaremos
a dependência o hibernate-annotation que por sua vez depende do hibernate-core:

<dependency org="org.hibernate" name="hibernate-annotations" rev="3.5.6-


Final"/>

Vamos copiar então essa dependência colando-a dentro do nosso ivy.xml. Só garantindo
através da configuração que apenas os JARs principais serão carregados, usando o
atributo conf="default":

<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info module="agenda" organisation="br.com.caelum" />

<dependencies>
<dependency org="org.hibernate" name="hibernate-annotations"
rev="3.5.6-Final" conf="default"/>
</dependencies>

</ivy-module>

Testando a configuração na linha de comando, executando ANT chamando o target


atualiza-tarefas, foram carregadas as dependências do hibernate-annotation e as
dependências transitivas.

No relatório podemos ver que foram carregados 10 artifacts:

atualiza-dependencias:
....
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.hibernate#hibernate-annotations;3.5.6-Final in
public
[ivy:retrieve] found org.hibernate#hibernate-core;3.5.6-Final in public
[ivy:retrieve] found antlr#antlr;2.7.6 in public
[ivy:retrieve] found commons-collections#commons-collections;3.1 in
public
[ivy:retrieve] found dom4j#dom4j;1.6.1 in public
[ivy:retrieve] found xml-apis#xml-apis;1.0.b2 in public
[ivy:retrieve] found javax.transaction#jta;1.1 in public
[ivy:retrieve] found org.slf4j#slf4j-api;1.5.8 in public
[ivy:retrieve] found org.hibernate#hibernate-commons-
annotations;3.2.0.Final in public
[ivy:retrieve] found org.hibernate.javax.persistence#hibernate-jpa-2.0-
api;1.0.0.Final in public
[ivy:retrieve] :: resolution report :: resolve 418ms :: artifacts dl 12ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 10 | 0 | 0 | 0 || 10 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 10 artifacts copied, 0 already retrieved (4461kB/18ms)
...

Voltando no projeto e atualizando-o, aparece a pasta lib com os JARs carregados, os


JARs principais e também os transitivos.

Desabilitando dependências
transitivas
O tag dependency do IVY possui elemento transitive que por padrão é true, mas
mudaremos para false para carregar apenas a dependência declarada, o hibernate-
annotation na versão 3.5.6.

atualiza-dependencias:
....
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.hibernate#hibernate-annotations;3.5.6-Final in
public
[ivy:retrieve] :: resolution report :: resolve 111ms :: artifacts dl 3ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 1 | 0 | 0 | 0 || 1 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 1 artifacts copied, 0 already retrieved (356kB/5ms)

Para continuar vamos deixar o elemento transitive="true".

Mais dependências e o primeiro


conflito
Em nossa aplicação queremos utilizar o Hibernate junto com JSF, escolhemos a
implementação MyFaces. Então vamos procurar pelo MyFaces no repositorio do Maven e
copiar a declaração da dependencia do Ivy, colando-a dentro do elemento dependencies,
garantindo também que será usada a configuração padrão apenas (conf="default"):

<dependency org="org.apache.myfaces.core" name="myfaces-impl" rev="2.1.7"


conf="default"/>

Testando novamente o build.xml. Chamando ant atualiza-dependencias mostra no


relatório que 15 artifacts foram usadas, mas 16 módulos foram carregados.

[ivy:retrieve] :: evicted modules:


[ivy:retrieve] commons-collections#commons-collections;3.1 by [commons-
collections#commons-collections;3.2] in [default]
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 16 | 0 | 0 | 1 || 15 | 0 |
---------------------------------------------------------------------

Podemos ver que um módulo foi tirado (evicted). Um pouco mais para cima é mostrado
qual dependência não foi usada, nesse caso a commons-collections na versão 3.1.
Olhando por dentro da pasta lib, percebemos que o commons-collections na versão 3.2
foi o escolhido, ou seja a versão mais recente.

Gerenciador de conflitos
Exite um gerenciador (conflict manager) que decide quais são os JAR a utilizar, mas
podemos decidir qual gerenciador utilizar. O conflict manager padrão se chama lastest-
revision, ou seja como já vimos, usa a versão mais nova, e por isso foi utilizado o
commons-collections na versão 3.2 . O gerenciador é definido o no ivy.xml:

<conflicts>
<manager name="latest-revision" />
</conflicts>

Mas podemos definir um outro conflict manager, por exemplo, all. Vamos testar o conflict
manager all executando novamente ANT.

Dentro do ivy.xml:

<conflicts>
<manager name="all" />
</conflicts>

Testando ant atualiza-dependencias:

[ivy:retrieve] :: resolution report :: resolve 588ms :: artifacts dl 22ms


---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 16 | 0 | 0 | 0 || 16 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 16 artifacts copied, 0 already retrieved (7427kB/210ms)

Podemos ver no relatório que foram 16 módulos carregados e 16 módulos adicionados. Ou


seja, foram carregadas as duas versões do commons-collections, a versão 3.1 E a
versão 3.2.

E também temos um conflict manager que se chama strict. Se algum conflito ocorrer,
nada é carregado e o build falha. No ivy.xml:

<conflicts>
<manager name="strict" />
</conflicts>
[ivy:retrieve] :: problems summary ::
[ivy:retrieve] :::: ERRORS
[ivy:retrieve] commons-collections#commons-collections;3.2 (needed by
[org.apache.myfaces.core#myfaces-impl;2.1.7]) conflicts with commons-
collections#commons-collections;3.1 (needed by [org.hibernate#hibernate-
core;3.5.6-Final])
[ivy:retrieve]
[ivy:retrieve] :: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS

BUILD FAILED

Vamos continuar usando o lastest-revision.

Criação do relatório de
dependências
Existe uma outra forma de visualizar as dependências. O Ivy vem uma tarefa já integrada
para gerar confortavelmente um relatório. Ela se chama ivy:report e recebe um atributo
que define o nome da pasta do relatório. Vamos gerar um relatório com Ivy na pasta
report:

<ivy:report todir="report"/>

O target fica como:

<target name="atualiza-dependencias" depends="limpar">


<ivy:retrieve />
<ivy:report todir="report"/>
</target>

Executando ANT novamente gerar então um relatório umas páginas html. Abrindo a
página html temos o status das dependências, os conflitos e um resumo de todas as
dependências. No nosso relatório temos duas dependências principais: o MyFaces e o
Hibernate-annotation e as dependências transitivas de cada um. Depois uma listagem de
cada dependência principal e transitiva.
Exclusão de dependências
Pode ainda, para cada dependência, solicitar a exclusão de alguma biblioteca para que
possamos adicionar a versão que desejamos. Para isso, em nosso exemplo, utilizaremos
tag exclude colocando o nome da biblioteca que queremos excluir, neste caso, vamos
excluir commons-collection. Para a dependência hibernate-anntoations e myfaces. No
ivy.xml:

<dependencies>

<dependency org="org.hibernate" name="hibernate-annotations" rev="3.5.6-


Final" transitive="true" conf="default">
<exclude name="commons-collections" />
</dependency>

<dependency org="org.apache.myfaces.core" name="myfaces-impl" rev="2.1.6"


conf="default">
<exclude name="commons-collections" />
</dependency>
</dependencies>
Agora vamos deixar o dependência commons-collections explicita, mas na versão 3.0.
Para que isso funcione, é necessário adicionar o elemento force com o valor true para
permitir que o elemento seja carregado:

<dependencies>

<dependency org="commons-collections" name="commons-collections"


force="true" rev="3.0" conf="default" />

<dependency org="org.hibernate" name="hibernate-annotations" rev="3.5.6-


Final" transitive="true" conf="default">
<exclude name="commons-collections" />
</dependency>

<dependency org="org.apache.myfaces.core" name="myfaces-impl" rev="2.1.6"


conf="default">
<exclude name="commons-collections" />
</dependency>
</dependencies>

Testando novamente com Ant:

---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 17 | 0 | 0 | 2 || 15 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#agenda
[ivy:retrieve] confs: [default]
[ivy:retrieve] 15 artifacts copied, 0 already retrieved (6833kB/273ms)

Podemos ver que também foram carregados 15 artefatos (de 17 modules) e o conflict
manager escolheu a versão 3.0 do commons-collections.

Resumo
Nesse vídeo vimos como resolver conflitos entre dependências transitivas com ivy. Em
nosso caso, ocorreu um conflito, pois as dependências do Hibernate e MyFaces,
utilizavam a mesma dependência transitiva: a commons-collections, mas em versões
diferentes.

No início da aula vimos como configurar o ivy para simplesmente ignorar as dependências
transitivas, usando o attribute transitive com valor falso.
Outra opção para excluir uma dependência específica, é embutir uma tag exclude.

Caso exista um conflito, quem tentará resolvê-lo é o gerenciador. O padrão usado é o


conflict manager latested-revision, que sempre utilizará a versão mais recente, porém,
podemos escolher outros gerenciadores como all ou strict.

Atividade 1 de 5
Se mandarmos o Ivy carregar versão 3.5.6-final da dependência hibernate-
annotations com a configuração default, ele carregará também suas dependências
transitivas por padrão. Assim, ao executarmos o comando ant, veremos que o Ivy
carregou 10 artefatos.

O que devemos fazer se não quisermos que o Ivy carregue as dependências transitivas?

17/12/2013 10:55

Adicionamos a task ivy:publish ao build

Mudamos o atributo transitive do elemento dependency para false

Omitimos o atributo conf do elemento dependency

Atividade 2 de 5
Quando tentamos carregar dependências que tenham as mesmas dependências
transitivas, é possível que ocorra um conflito. Para tentar resolver esse problema, o Ivy
usa um gerenciador de conflitos (conflict-manager) padrão chamado latest-revision,
que carrega apenas a versão mais recente da dependência.

Que linha devemos usar se quisermos que o Ivy carregue todas as dependências?

Atividade 3 de 5
Podemos também fazer com que o build pare e o Ivy não carregue nada caso ocorra um
conflito. Para isso, que conflict manager devemos usar?

Atividade 4 de 5
Qual gerenciador de conflitos (conflict-manager) escolhe a dependência com a versão
mais nova sem abortar o build?

17/12/2013 10:55

strict

latest-compatible

latest-revision

all

latest-time

Atividade 5 de 5
Qual a tag é utilizada para excluir uma dependência transitiva?

17/12/2013 10:56

ignore

skip


delete

evict

exclude

Explicação

Apresentação do projeto
Temos um projeto já pre-configurado no Eclipse. Ele se chama o security-api que possui
uma pasta src para o código fonte com as classes para simular uma biblioteca de
segurança. Dentro do projeto já se encontra a biblioteca do Ivy e os arquivos XMLs
build.xml e ivy.xml.

No ivy.xml temos o elemento info configurado com o nome do módulo, a organização e


uma dependência ao Spring Framework na versão 3.1.1 usando a configuração default.

Veja o conteúdo do arquivo ivy.xml:

<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info module="security-api" organisation="br.com.caelum" />

<dependencies>
<dependency org="org.springframework" name="spring-core"
rev="3.1.1.RELEASE" conf="default" />
</dependencies>

</ivy-module>

O build.xml do ANT define a propriedade build.dir, o caminho (path) e a tarefa para


usar o Ivy com o namespace configurado na declaração do projeto. Além disso, existem
quatro targets definidos:

 clean - target para limpar e recriar a pasta build


 retrieve - target para carregar as dependências com IVY
 compile - target para compilar, depende de clean e retrieve
 jar - target para empacotar a aplicação

O conteúdo do build.xml fica:

<project name="security-api" xmlns:ivy="antlib:org.apache.ivy.ant" >

<property name="build.dir" value="build"/>

<path id="ivy.lib.path">
<fileset dir="ivy-lib" includes="*.jar"/>
</path>

<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>

<target name="clean">
<delete dir="${build.dir}" />
<mkdir dir="${build.dir}" />
</target>

<target name="retrieve" >


<ivy:retrieve />
</target>

<target name="compile" depends="clean, retrieve">


<javac srcdir="src" destdir="${build.dir}">
<classpath>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</classpath>
</javac>
</target>

<target name="jar" depends="compile">


<jar destfile="${build.dir}/${ant.project.name}.jar" basedir="$
{build.dir}" />
</target>
</project>

Testando o build
Vamos testar o build.xml na linha de comando com ANT, entrando no workspace e na
pasta do projeto. Podemos mostrar todos os targets disponíveis com o comando:

ant -p

Mostra: (clean, compile, jar, retrieve)

Depois podemos executar a tarefa jar chamando:

ant jar

Apresenta:

Buildfile: /Users/caelum/Documents/IVY/IVY-workspace/security-api/build.xml

clean:
[delete] Deleting directory /Users/caelum/Documents/IVY/IVY-
workspace/security-api/build
[mkdir] Created dir: /Users/caelum/Documents/IVY/IVY-workspace/security-
api/build

retrieve:
[ivy:retrieve] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /Users/caelum/Documents/IVY/IVY-
workspace/security-api/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: br.com.caelum#security-
api;working@MacBook-Pro-de-Caelum.local
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.springframework#spring-core;3.1.1.RELEASE
[ivy:retrieve] found org.springframework#spring-asm;3.1.1.RELEASE
[ivy:retrieve] found commons-logging#commons-logging;1.1.1
[ivy:retrieve] :: resolution report :: resolve 273ms :: artifacts dl 5ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 3 | 0 | 0 | 0 || 3 | 0 |
---------------------------------------------------------------------
[ivy:retrieve]
....
compile:
[javac] /Users/caelum/Documents/IVY/IVY-workspace/security-
api/build.xml:27: warning: 'includeantruntime' was not set, defaulting to
build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 1 source file to /Users/caelum/Documents/IVY/IVY-
workspace/security-api/build

jar:
[jar] Building jar: /Users/caelum/Documents/IVY/IVY-workspace/security-
api/build/security-api.jar

BUILD SUCCESSFUL
Total time: 2 seconds

Na saida fica visível que foram carregadas as dependências do Spring Framework


(ivy:retrieve). Também foi gerado o JAR da nossa biblioteca security-api que possui
todas as classes compiladas.

Definição do artefato a publicar


Para esta seção queremos publicar o arquivo security-api.jar dentro de um repositório
próprio. O primeiro passo é adicionar um elemento no ivy.xml que se chama
publications, aqui serão declarados todos os artefatos que queremos adicionar dentro do
repositório. O elemento publications recebe a declaração do artefato a publicar. O
artefato em si contem seguintes atributos:

 name - em nosso caso security-api


 ext - a extensão este artefato é um ponto jar
 type - este artefato é do tipo JAR

Segue o ivy.xml com o novo elemento publications:

<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info module="security-api" organisation="br.com.caelum" />

<publications>
<artifact name="security-api" type="jar" ext="jar"/>
</publications>
<dependencies>
<dependency org="org.springframework" name="spring-core"
rev="3.1.1.RELEASE" conf="default" />
</dependencies>

</ivy-module>

Tarefa para publicar


Dentro do ivy.xml declaramos os artefatos que queremos publicar mas quem fará o
trabalho realmente é o ANT. Para isso vamos adicionar um novo target dentro do
build.xml. Chamaremos esse target de publish, porque queremos publicar o nosso JAR.
O Ivy oferece uma tarefa, ivy:publish, para este fim. A primeira versão do build.xml
fica:

<project name="security-api" xmlns:ivy="antlib:org.apache.ivy.ant" >


.....
<target name="publish" depends="jar" >
<ivy:publish>
<!-- o que queremos publicar? -->
</ivy:publish>
</target>
.....
</project>

Dentro da tarefa ivy:publish vamos adicionar os artifacts que gostaríamos de publicar.


Definiremos um pattern, que indica onde se encontram nossos artifacts. Em nosso caso
estão na pasta build.dir, seguido pelo o nome do artifacto ([artifact] ou seja
security-api) com a extensão ([ext]) jar. Veja como fica a definição completa do target:

<project name="security-api" xmlns:ivy="antlib:org.apache.ivy.ant" >


.....
<target name="publish" depends="jar" >
<ivy:publish>
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>
….
</project>
Além disso, do pattern a tarefa ivy:publish deveria definir a versão do artefato, em nosso
caso 1.0 e o estatus do projeto (beta, alfa, release), mas em nosso caso usaremos
RELEASE. Veja o target no build.xml:

<target name="publish" depends="jar" >


<ivy:publish status="release" pubrevision="1.0" overwrite="true" >
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>

Publicação de vários tipos de


artefatos
Poderia ser interessante publicar tipo de artefatos diferentes. Além do JAR com os classes
compiladas podemos, por exemplo, publicar um JAR com o javadoc, ou um outro com o
código fonte. Nesse caso faria sentido distinguir o artefato pelo nome E o tipo. Por isso
podemos definir na tarefa ivy:publish um pattern que define o tipo ( [type] ):

<target name="publish" depends="jar" >


<ivy:publish status="release" pubrevision="1.0" overwrite="true" >
<artifacts pattern="${build.dir}/[artifact]-[type].[ext]"/>
</ivy:publish>
</target>

Segue um exemplo com dois artefatos no elemento publications do ivy.xml. Repare


que também foi declarado um artefato com o javadoc:

<publications>
<artifact name="security-api-jar" type="jar" ext="jar"/>
<artifact name="security-api-javadoc" type="javadoc" ext="jar"/>
</publications>

Publicação e resolvers
Vamos testar o target publish executando o ANT na linha de comando:

ant publish

Com a saída:

.....
jar:
[jar] Building jar: /Users/caelum/Documents/IVY/IVY-workspace/IVY-
repository/security-api/build/security-api.jar
publish:
BUILD FAILED
/Users/caelum/Documents/IVY/IVY-workspace/IVY-repository/security-api/
build.xml:36: no publish deliver name: please provide it through parameter
'resolver'

Podemos ver que o ANT gerou um erro e acusou um parâmetro resolver. O problema é
que Ivy não sabe para onde publicar o nosso JAR. Para isso é preciso criar um arquivo de
configuração, o ivysettings.xml. Este arquivo define esse local do repositório.

No ivy.xml vamos adicionar um elemento ivysettings. Dentro dessa tag vem um outro
elemento resolvers que define o novo repositorio, no nosso caso é baseado no
filesystem local. Vamos dar um nome para esse repositório: ivyrepolocal. Dentro do
filesystem vamos adicionar novamente um pattern para nossos artifacts, definindo o local
onde ficarão os JAR. Veja o ivysettings.xml completo:

<ivysettings>
<settings defaultResolver="ivyrepolocal" />
<resolvers>
<filesystem name="ivyrepolocal">
<artifact pattern="${user.home}/ivyrepolocal/[module]/[artifact]-
[revision].[ext]" />
<ivy pattern="${user.home}/ivyrepolocal/[module]/ivy-[revision].xml"
/>
</filesystem>
</resolvers>
</ivysettings>

O user.home indica a pasta do usuário. Lá dentro será criado uma pasta ivyrepolocal,
seguido por uma pasta com o nome do [module], do [artifact], colocando a [revision]
e a extensão ( [ext] ). Cada artefato é sempre acompanhado pelo um ivy.xml, para isso
também definiremos um ivy pattern.

Além dos patterns foi definido um elemento para declarar o resolver padrão. No nosso
caso é o ivyrepolocal. Finalmente usaremos o nome desse resolver no target publish
do build.xml:

<target name="publish" depends="jar">


<ivy:publish pubrevision="1.0" status="release" overwrite="true"
resolver="ivyrepolocal">
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>

Vamos chamar o ANT novamente:

ant publish
Com a saída:

compile:
[javac] /Users/caelum/Documents/IVY/IVY-workspace/IVY-
repository/security-api/build.xml:22:
warning: 'includeantruntime' was not set, defaulting to
build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 1 source file to
/Users/caelum/Documents/IVY/IVY-workspace/IVY-repository/security-api/build

jar:
[jar] Building jar:
/Users/caelum/Documents/IVY/IVY-workspace/IVY-repository/security-api/build/
security-api.jar

publish:
[ivy:publish] :: delivering ::
br.com.caelum#security-api;working@MacBook-Pro-de-Caelum.local :: 1.0
:: release :: Wed Aug 15 18:25:23 BRT 2012
[ivy:publish] delivering ivy file to
/Users/caelum/Documents/IVY/IVY-workspace/IVY-repository/security-api/build/
ivy.xml
[ivy:publish] :: publishing :: br.com.caelum#security-api
[ivy:publish] published security-api to
/Users/caelum/ivyrepolocal/security-api/security-api-1.0.jar
[ivy:publish] published ivy to
/Users/caelum/ivyrepolocal/security-api/ivy-1.0.xml

Foram publicados dentro da pasta do usuário, na pasta ivyrepolocal e nossa biblioteca


security-api-1.0.jar e o XML com o conteúdo do nosso ivy.xml.

Baixar dependências do
repositório local
O próximo passo é usar essa dependência dentro de um outro projeto. Para isso vamos
criar um novo projeto e chamá-lo de application. Será usado um projeto java comum.
Nesse projeto novo copiaremos o ivy.xml e build.xml e a bibliteco do IVY do projeto
anterior.
O ivy.xml será mais simples e não terá o elemento publications. E nome do modulo
será application, organization continua da mesma forma. A dependência não será mais
o springframework, ela será do módulo security-api na versão 1.0:

<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-


instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

<info module="application" organisation="br.com.caelum" />

<dependencies>
<dependency org="br.com.caelum" name="security-api" rev="1.0"
conf="default" />
</dependencies>

</ivy-module>

No build.xml não publicaremos nada e também não geraremos um JAR. Só vamos


compilar e baixar as dependências da nossa aplicação. O build.xml fica um pouco mais
simples:

<project name="security-api" xmlns:ivy="antlib:org.apache.ivy.ant" >

<property name="build.dir" value="build"/>

<path id="ivy.lib.path">
<fileset dir="ivy-lib" includes="*.jar"/>
</path>

<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>

<target name="clean">
<delete dir="${build.dir}" />
<mkdir dir="${build.dir}" />
</target>

<target name="retrieve" >


<ivy:retrieve />
</target>
<target name="compile" depends="clean, retrieve">
<javac srcdir="src" destdir="${build.dir}">
<classpath>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</classpath>
</javac>
</target>
</project>

Vamos testar o ANT na linha de comando, entrando no projeto application</code,


chamando:

ant compile
Buildfile: /Users/admin/dev/IVY-repository/application/build.xml

clean:
[delete] Deleting directory /Users/admin/dev/IVY-
repository/application/build
[mkdir] Created dir: /Users/admin/dev/IVY-repository/application/build

retrieve:
[ivy:retrieve] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /Users/admin/dev/IVY-
repository/application/ivysettings.xml
[ivy:retrieve] :: resolving dependencies ::
br.com.caelum#application;working@admins-MacBook-Air.local
[ivy:retrieve] confs: [default]
[ivy:retrieve] found br.com.caelum#security-api;1.0 in ivyrepolocal
[ivy:retrieve] found org.springframework#spring-core;3.1.1.RELEASE in
ivyrepolocal
[ivy:retrieve] found org.springframework#spring-asm;3.1.1.RELEASE in
ivyrepolocal
[ivy:retrieve] found commons-logging#commons-logging;1.1.1 in
ivyrepolocal
[ivy:retrieve] downloading /Users/admin/ivyrepolocal/security-api/security-
api-1.0.jar ...
[ivy:retrieve] .. (0kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] br.com.caelum#security-api;1.0!security-
api.jar (6ms)
[ivy:retrieve] :: resolution report :: resolve 327ms :: artifacts dl 21ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 4 | 1 | 1 | 0 || 4 | 1 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#application
[ivy:retrieve] confs: [default]
[ivy:retrieve] 1 artifacts copied, 3 already retrieved (0kB/7ms)

compile:
[javac] /Users/admin/dev/IVY-repository/application/build.xml:23:
warning: 'includeantruntime'
BUILD SUCCESSFUL

Como o target compile usa

retrieve ele carrega as dependências por de baixo dos panos. Carregou quatro jars, o JAR
da nossa biblioteca e as dependências transistivas.

Definição do repositório local


Voltando para o Eclipse, atualizando o projeto, podemos ver as 4 dependências,
security-api e as dependências transitivas. Mas como isso funcionou? Porque dentro
deste projeto, em nenhum lugar definimos o repositório local e nossa dependência só se
encontra aparentemente no repositório local.

O detalhe que não sabemos ainda é que por padrão, o IVY nem olha no repositorio por
padrão. Se o IVY acha dentro da pasta do usuário, uma pasta especial escondida que se
chama .ivy2, ele procura as dependências ali. Esta pasta é um cache local e se o IVY
encontra nesssa pasta os JARs, ele não procurará mais nos repositórios.

Olhando nessa pasta cache achamos nossa dependência de segurança e também as


dependências transitivas do apache e do spring framework. Ou seja, apagando essa pasta
.ivy2, o IVY é obrigatório de procurar as dependências nos repositórios e consequente
deve dar erro pois não configuramos o repositório local no projeto application.

Vamos então apagar esta pasta e depois chamar novamento o comando ant compile:

[ivy:retrieve] confs: [default]


[ivy:retrieve] :: resolution report :: resolve 1662ms :: artifacts dl 0ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 1 | 0 | 0 | 0 || 0 | 0 |
---------------------------------------------------------------------
[ivy:retrieve]
[ivy:retrieve] :: problems summary ::
[ivy:retrieve] :::: WARNINGS
[ivy:retrieve] module not found: br.com.caelum#security-api;1.0
[ivy:retrieve] ==== local: tried
[ivy:retrieve] /Users/admin/.ivy2/local/br.com.caelum/security-
api/1.0/ivys/ivy.xml
[ivy:retrieve] -- artifact br.com.caelum#security-api;1.0!security-
api.jar:
[ivy:retrieve] /Users/admin/.ivy2/local/br.com.caelum/security-
api/1.0/jars/security-api.jar
[ivy:retrieve] ==== shared: tried
[ivy:retrieve] /Users/admin/.ivy2/shared/br.com.caelum/security-
api/1.0/ivys/ivy.xml
[ivy:retrieve] -- artifact br.com.caelum#security-api;1.0!security-
api.jar:
[ivy:retrieve] /Users/admin/.ivy2/shared/br.com.caelum/security-
api/1.0/jars/security-api.jar
[ivy:retrieve] ==== public: tried
[ivy:retrieve] http://repo1.maven.org/maven2/br/com/caelum/security-
api/1.0/security-api-1.0.pom
[ivy:retrieve] -- artifact br.com.caelum#security-api;1.0!security-
api.jar:
[ivy:retrieve] http://repo1.maven.org/maven2/br/com/caelum/security-
api/1.0/security-api-1.0.jar
[ivy:retrieve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:retrieve] :: UNRESOLVED DEPENDENCIES ::
[ivy:retrieve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:retrieve] :: br.com.caelum#security-api;1.0: not found
[ivy:retrieve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:retrieve]
[ivy:retrieve] :: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS

BUILD FAILED
/Users/admin/dev/IVY-repository/application/build.xml:19: impossible to
resolve dependencies:
resolve failed - see output for details

IVY tenta carregar a nossa biblioteca security-api mas não consegue resolver pois
procurou no repositorio padrão, o Maven Repositorio. É claro que nossa biblioteca
recentemente criada não está publicada lá.

Para resolver isso vamos configurar o repositório local dentro do projeto application. Isto
é feito através da mesma configuração já usada dentro do ivysettings.xml. Vamos
adicionar este arquivo no projeto dentro da pasta src:

<ivysettings>
<settings defaultResolver="ivyrepolocal" />
<resolvers>
<filesystem name="ivyrepolocal">
<artifact pattern="${user.home}/ivyrepolocal/[module]/[artifact]-
[revision].[ext]" />
<ivy pattern="${user.home}/ivyrepolocal/[module]/ivy-
[revision].xml" />
</filesystem>
</resolvers>
</ivysettings>

Agora podemos testar na linha de comando:

ant compile

Com a saída:

retrieve:
[ivy:retrieve] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /Users/admin/dev/IVY-
repository/application/ivysettings.xml
[ivy:retrieve] :: resolving dependencies ::
br.com.caelum#application;working@admins-MacBook-Air.local
[ivy:retrieve] confs: [default]
[ivy:retrieve] found br.com.caelum#security-api;1.0 in ivyrepolocal
[ivy:retrieve] downloading /Users/admin/ivyrepolocal/security-api/security-
api-1.0.jar ...
[ivy:retrieve] .. (0kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] br.com.caelum#security-api;1.0!security-
api.jar (5ms)
[ivy:retrieve] :: resolution report :: resolve 175ms :: artifacts dl 7ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 2 | 1 | 1 | 0 || 1 | 1 |
---------------------------------------------------------------------
[ivy:retrieve]
[ivy:retrieve] :: problems summary ::
[ivy:retrieve] :::: WARNINGS
[ivy:retrieve] module not found: org.springframework#spring-
core;3.1.1.RELEASE
[ivy:retrieve] ==== ivyrepolocal: tried
[ivy:retrieve] /Users/admin/ivyrepolocal/spring-core/ivy-
3.1.1.RELEASE.xml
[ivy:retrieve] -- artifact org.springframework#spring-
core;3.1.1.RELEASE!spring-core.jar:
[ivy:retrieve] /Users/admin/ivyrepolocal/spring-core/spring-core-
3.1.1.RELEASE.jar
[ivy:retrieve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:retrieve] :: UNRESOLVED DEPENDENCIES ::
[ivy:retrieve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:retrieve] :: org.springframework#spring-core;3.1.1.RELEASE: not
found
[ivy:retrieve] ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:retrieve]
[ivy:retrieve] :: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS

BUILD FAILED
/Users/admin/dev/IVY-repository/application/build.xml:19: impossible to
resolve dependencies: resolve failed - see output for details

O IVY achou a dependência security-api mas não encontrou as dependências


transitivas, os JARs do spring framework.

Configuração da cadeia de
repositórios
Não foram encontradas as dependências transitivas. Isso ocorreu porque as dependências
transitivas vem do repositório do Maven. Nos definimos apenas um repositório local, agora
é preciso definir tambem o do Maven.
Declararemos um novo resolver que representa o repositório do Maven. Este resolver se
chama ibiblio por padrão. Para usar os dois resolvers, ibiblio e ivyrepolocal, em
conjunto vamos definir uma cadeia de resolvers (chain). Veja como que fica o arquivo
ivysettings.xml:

<ivysettings>

<settings defaultResolver="repochain" />

<resolvers>
<chain name="repochain">
<ibiblio m2compatible="true" name="mavenrepo"/>
<filesystem name="ivyrepolocal">
<artifact
pattern="${user.home}/ivyrepolocal/[module]/[artifact]-[revision].[ext]" />
<ivy pattern="${user.home}/ivyrepolocal/[module]/ivy-
[revision].xml" />
</filesystem>
</chain>
</resolvers>
</ivysettings>

Como chain é composto pelo repositório do Maven e nosso repositório local o IVY vai
procurar em ambos lugares as dependências. Repare também que o defaultResolver se
chama repochain.

Testando denovo na linha de comando:

ant compile
retrieve:
[ivy:retrieve] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /Users/admin/dev/IVY-
repository/application/ivysettings.xml
[ivy:retrieve] :: resolving dependencies ::
br.com.caelum#application;working@admins-MacBook-Air.local
[ivy:retrieve] confs: [default]
[ivy:retrieve] found br.com.caelum#security-api;1.0 in ivyrepolocal
[ivy:retrieve] found org.springframework#spring-core;3.1.1.RELEASE in
mavenrepo
[ivy:retrieve] found org.springframework#spring-asm;3.1.1.RELEASE in
mavenrepo
[ivy:retrieve] found commons-logging#commons-logging;1.1.1 inmavenrepo
[ivy:retrieve] downloading
http://repo1.maven.org/maven2/org/springframework/spring-core/3.1.1.RELEASE/
spring-core-3.1.1.RELEASE.jar ...
[ivy:retrieve] ..............................................................
..........
[ivy:retrieve] ...................
[ivy:retrieve] ............................................
[ivy:retrieve] .................................
[ivy:retrieve] ................................................
[ivy:retrieve] ................................ (438kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] org.springframework#spring-
core;3.1.1.RELEASE!spring-core.jar (10527ms)
[ivy:retrieve] downloading
http://repo1.maven.org/maven2/org/springframework/spring-asm/3.1.1.RELEASE/
spring-asm-3.1.1.RELEASE.jar ...
[ivy:retrieve] ..................................... (51kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] org.springframework#spring-
asm;3.1.1.RELEASE!spring-asm.jar (2133ms)
[ivy:retrieve] downloading
http://repo1.maven.org/maven2/commons-logging/commons-logging/1.1.1/commons-
logging-1.1.1.jar ...
[ivy:retrieve] .......................................... (59kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] commons-logging#commons-logging;1.1.1!
commons-logging.jar (2045ms)
[ivy:retrieve] :: resolution report :: resolve 17028ms :: artifacts dl
14712ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 4 | 3 | 3 | 0 || 4 | 3 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: br.com.caelum#application
[ivy:retrieve] confs: [default]
[ivy:retrieve] 0 artifacts copied, 4 already retrieved (0kB/5ms)

compile:
[javac] /Users/admin/dev/IVY-repository/application/build.xml:23:
warning: 'includeantruntime' was not set, defaulting to
build.sysclasspath=last; set to false for repeatable builds

BUILD SUCCESSFUL

Foram encontradas todas as bibliotecas, incluindo as dependências transitivas.

Instalando todas as
dependências no repositório
local
Para nossa aplicação não desejamos usar um repositório publico. Todas as dependências
devem se encontrar dentro do repositório local. Então vamos apagar a cadeia de resolver
dentro de ivysettings.xml e continuar utilizando apenas o repolocal como padrão:

<ivysettings>
<settings defaultResolver="ivyrepolocal" />
<resolvers>
<filesystem name="ivyrepolocal">
<artifact pattern="${user.home}/ivyrepolocal/[module]/[artifact]-
[revision].[ext]" />
<ivy pattern="${user.home}/ivyrepolocal/[module]/ivy-
[revision].xml" />
</filesystem>
</resolvers>
</ivysettings>

Todas as dependências devem estar dentro do repositório local. Para nossa aplicação isso
significa que além do security-api também o spring framework deve ficar no repositório
local.

Há uma tarefa do IVY que podemos usar dentro do build.xml para copiar qualquer
dependência entre repositiórios. No nosso caso queremos copiar o spring framework do
repositório do Maven para o nosso repositório local. A tarefa se chama ivy:install:

<target name="install">
<ivy:install from="mavenrepo" to="ivyrepolocal"
organisation="org.springframework" module="spring-core"
revision="3.1.1.RELEASE" transitive="true" overwrite="true" />
</target>

Aqui declaramos que queremos instalar do (from) mavenrepo para (to) ivyrepolocal,
overwrite=”true” para sobreescrever e definindo a organização, modulo e revisão.
Chamando a tarefa com Ant:

ant install

Mostra a saída:

install:
[ivy:install] :: Ivy 2.2.0 - 20100923230623 :: http://ant.apache.org/ivy/ ::
[ivy:install] :: loading settings :: file = /Users/admin/dev/IVY-
repository/security-api/ivysettings.xml
[ivy:install] :: installing org.springframework#spring-core;3.1.1.RELEASE ::
[ivy:install] :: resolving dependencies ::
[ivy:install] found org.springframework#spring-core;3.1.1.RELEASE in
mavenrepo
[ivy:install] found org.springframework#spring-asm;3.1.1.RELEASE in
mavenrepo
[ivy:install] found commons-logging#commons-logging;1.1.1 in mavenrepo
[ivy:install] found commons-collections#commons-collections;3.2 in
mavenrepo
[ivy:install] found log4j#log4j;1.2.15 in mavenrepo
[ivy:install] found net.sf.jopt-simple#jopt-simple;3.0 in mavenrepo
[ivy:install] found org.apache.ant#ant;1.7.0 in mavenrepo
[ivy:install] found org.apache.ant#ant-launcher;1.7.0 in mavenrepo
[ivy:install] found org.aspectj#aspectjweaver;1.6.8 in mavenrepo
[ivy:install] :: downloading artifacts to cache ::
[ivy:install] downloading …..........
[ivy:install] .. (0kB)
[ivy:install] [SUCCESSFUL ] org.apache.ant#ant;1.7.0!ant.jar (7431ms)
[ivy:install] downloading http://repo1.maven.org/maven2/org/apache/ant/ant-
launcher/1.7.0/ant-launcher-1.7.0.jar ...
[ivy:install] .......... (11kB)
[ivy:install] .. (0kB)
[ivy:install] [SUCCESSFUL ] org.apache.ant#ant-launcher;1.7.0!ant-
launcher.jar (608ms)
[ivy:install] :: installing in ivyrepolocal ::
[ivy:install] published spring-core to /Users/admin/ivyrepolocal/spring-
core/spring-core-3.1.1.RELEASE.jar
[ivy:install] published spring-core to /Users/admin/ivyrepolocal/spring-
core/spring-core-3.1.1.RELEASE.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/spring-core/ivy-
3.1.1.RELEASE.xml
[ivy:install] published spring-asm to /Users/admin/ivyrepolocal/spring-
asm/spring-asm-3.1.1.RELEASE.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/spring-asm/ivy-
3.1.1.RELEASE.xml
[ivy:install] published commons-logging to
/Users/admin/ivyrepolocal/commons-logging/commons-logging-1.1.1.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/commons-
logging/ivy-1.1.1.xml
[ivy:install] published commons-collections to
/Users/admin/ivyrepolocal/commons-collections/commons-collections-3.2.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/commons-
collections/ivy-3.2.xml
[ivy:install] published log4j to /Users/admin/ivyrepolocal/log4j/log4j-
1.2.15.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/log4j/ivy-
1.2.15.xml
[ivy:install] published jopt-simple to /Users/admin/ivyrepolocal/jopt-
simple/jopt-simple-3.0.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/jopt-simple/ivy-
3.0.xml
[ivy:install] published aspectjweaver to
/Users/admin/ivyrepolocal/aspectjweaver/aspectjweaver-1.6.8.jar
[ivy:install] published ivy to
/Users/admin/ivyrepolocal/aspectjweaver/ivy-1.6.8.xml
[ivy:install] published ant to /Users/admin/ivyrepolocal/ant/ant-
1.7.0.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/ant/ivy-
1.7.0.xml
[ivy:install] published ant-launcher to /Users/admin/ivyrepolocal/ant-
launcher/ant-launcher-1.7.0.jar
[ivy:install] published ivy to /Users/admin/ivyrepolocal/ant-
launcher/ivy-1.7.0.xml
[ivy:install] :: install resolution report ::
[ivy:install] :: resolution report :: resolve 0ms :: artifacts dl 48147ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 9 | 6 | 6 | 0 || 10 | 7 |
---------------------------------------------------------------------

BUILD SUCCESSFUL
Total time: 1 minute 9 seconds
Foram instalados todas as dependências e dependências transitivas no repositório local.

Resumo
Nessa aula vimos como trabalhar com dois repositórios. O primeiro era o repositório
publico do Maven, o segundo um repositório local. O repositório local era preciso porque
criamos uma biblioteca própria e não queríamos disponibilizar ela dentro do repositório
publico do Maven. Usamos a tarefa ivy:publish para publicar o artefato dentro do nosso
repositório local. Dessa maneira outras maquinas e projetos podem declarar a
dependência também referenciando o repositório local. Para definir os repositórios usamos
o arquivo de configuração, ivysettings.xml. Caso quiséssemos ficar independente do
repositório publico do Maven, é preciso instalar todas as dependências e dependências
transitivas no repositório local. Fizemos isso através da tarefa do ivy:install.

Atividade 1 de 6
Como se chama a tarefa do Ivy para publicar as dependências no repositório?

17/12/2013 10:59

publish

push

retrieve

install

Atividade 2 de 6
Como se chama a tarefa para copiar uma dependências entre repositórios?

17/12/2013 11:00


copy

transfer

install

move

Atividade 3 de 6
Por que poderia fazer sentido usar um repositório local apenas acessível para
desenvolvedores da empresa?

Atividade 4 de 6
Dado a seguinte tarefa no build.xml:

<target name="publicar">
<ivy:publish pubrevision="1.0" status="release" overwrite="true"
resolver="ivyrepolocal">
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>

O ivysettings.xml:

<ivysettings>
<settings defaultResolver="ivyrepolocal" />
<resolvers>
<filesystem name="ivyrepolocal">
<artifact pattern="/home/admin/repo/[module]/[artifact]-[revision].
[ext]" />
<ivy pattern="/home/admin/repo/[module]/ivy-[revision].xml" />
</filesystem>
</resolvers>
</ivysettings>
Em que pasta será publicado o modulo security?

Atividade 5 de 6
Qual das seguintes afirmações é verdadeira?

17/12/2013 11:03

O repositório ibiblio é o repositório local.

Com Ivy só pode ser utilizado um repositório no projeto.

O resolver padrão do projeto é sempre aquele que usa o repositório do Maven.

Para ultilizar mais do que um repositório é preciso definir um cadeia de resolvers.

A cadeia de resolvers é configurada no ivy.xml

Atividade 6 de 6
Baixe o projeto security-api aqui .

Esse projeto está com o build quebrado. Ao executar ant publish na raiz do projeto
percebemos que o build está falhando com a mensagem seguinte:

Buildfile: /Users/caelum/Documents/workspace/security-api/build.xml

........

publish: [ivy:publish] :: delivering :: br.com.caelum#security-


api;working@Mac-Caelum.local :: 1.0 :: release :: Fri Aug 24 11:58:23 BRT
2012 [ivy:publish] delivering ivy file to
/Users/caelum/Documents/workspace/security-api/build/ivy.xml [ivy:publish] ::
publishing :: br.com.caelum#security-api
BUILD FAILED /Users/caelum/Documents/workspace/security-api/build.xml:35:
impossible to publish artifacts for br.com.caelum#security-api;working@Mac-
Caelum.local:

java.lang.IllegalArgumentException: unknown resolver ivyrepolocal at


org.apache.ivy.core.publish.PublishEngine.publish(PublishEngine.java:168) at
org.apache.ivy.Ivy.publish(Ivy.java:600) at
org.apache.ivy.ant.IvyPublish.doExecute(IvyPublish.java:311) at
org.apache.ivy.ant.IvyTask.execute(IvyTask.java:277) at
org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.
java:25) at java.lang.reflect.Method.invoke(Method.java:597) at
org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348) at
org.apache.tools.ant.Target.execute(Target.java:392) at
org.apache.tools.ant.Target.performTasks(Target.java:413) at
org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399) at
org.apache.tools.ant.Project.executeTarget(Project.java:1368) at
org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.ja
va:41) at org.apache.tools.ant.Project.executeTargets(Project.java:1251) at
org.apache.tools.ant.Main.runBuild(Main.java:811) at
org.apache.tools.ant.Main.startAnt(Main.java:217) at
org.apache.tools.ant.launch.Launcher.run(Launcher.java:280) at
org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

Total time: 1 second

Conserte o build e crie o ivysettings.xml para definir o resolver. Cole na sua resposta o
arquivo completo.

Você também pode gostar