optimal chain for resolve in ivy - ant

I have some project's that integrates ivy, i publish my artifact in two possible repositories, local, that respond to a folder, and beta, that respond to a server where archiva is installed and where i share my jars with my colleague.
Now the problem: i need to find a way to build a resolution chains that do this things:
search between the various repository the latest.integration.
retrieve that jar.
if that jar is already in my cache do not have to download it.
if the artifact in the cache has the same version of the artifact in one of the repository take the latest in chronology's order.
now i have try everything that's the setting
Ivy setting
<chain name="resolvechain">
<ibiblio name="b1" root="archivaURLforbeta" m2compatible="true" checkmodified="true" latest="latest-time"/>
<filesystem name="b2" checkmodified="true" >
<artifact pattern="${ivy.local.default.root}/${ivy.local.default.artifact.pattern}" />
</filesystem>
<ibiblio name="b3" root="archivaURLforrelease" m2compatible="true" latest="latest-time"/>
<ibiblio name="b4" m2compatible="true"/>
</chain>
that's the target of resolve in the Build.xml file:
<ivy:settings file="${archiva.set}" />
<ivy:resolve refresh="true" resolveMode="dynamic" changing="true"/>
<ivy:retrieve sync="true" overwritemode="newer" pattern="./lib/[artifact]-[type]-[revision](.[ext])" />
and that's an example on how the dependency are written in ivy.xml file
<dependency org="organization" name="module-name" rev="latest.integration" transitive="false" conf="default" />
the questions are two:
First of all is there any error according to my needs?
Second, what i'm trying to do, is possible?
i asked these two questions because it seems to me that setting checkmodified true and changing true let my application skip entirely my cache, and my projects continuing to download the artifacts every time.

I have found the solution searching between different questions here in stackoverflow and in some issues solution in the ivy comunity with my colleagues.
The FileSystem need it's own latest-time strategy, every resolve take note of their own modules last date revision.
Here the mod in the code:
<filesystem name="b2" checkmodified="true" latest="latest-time">
<artifact pattern="${ivy.local.default.root}/${ivy.local.default.artifact.pattern}" />
</filesystem>

Related

How to publish custom jars to local Apache Ivy repository

I've read all the tutorials and examples, and still cannot publish a set of custom jars in my local Ivy repository.
Edit: Basically I want the same behavior as maven-install-plugin.
Here's my setup. I have an Ant task which produces the jars in a given folder. The folder name is not fixed but rather passed as a property in file. I want to get all the jars in this folder and install them in my local Ivy repo so that I can use them on a next step.
Here is my Ant from where I call the ivy:publish:
<project name="Install Ivy Dependencies" xmlns:ivy="antlib:org.apache.ivy.ant" basedir="." default="publish">
<loadproperties srcFile="path_to_folder.properties"/>
<property name="file_pattern" value="${path_to_folder}/[artifact].[ext]" />
<property name="pub_revision" value="1.0.0" />
<target name="resolve">
<ivy:configure file="ivysettings.xml" />
<ivy:resolve file="ivy.xml" />
</target>
<target name="retrieve-all" depends="resolve">
<ivy:retrieve pattern="${file_pattern}" conf="*" />
</target>
<target name="publish" depends="retrieve-all">
<ivy:publish resolver="local" organisation="myOrg" update="true" overwrite="true" pubrevision="${pub_revision}">
<artifacts pattern="${file_pattern}"/>
</ivy:publish>
</target>
</project>
Here's my ivysettings.xml:
<ivysettings>
<resolvers>
<filesystem name="local" local="true"/>
</resolvers>
</ivysettings>
And the ivy.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="myOrg" module="myModule" revision="1.0.0"/>
<publications>
<artifact name="my-custom-jar" ext="jar" type="jar"/>
<artifact name="my-custom-jar-source" ext="jar" type="source"/>
</publications>
</ivy-module>
The error that I am getting when I call the ant task is:
impossible to publish artifacts for myOrg#myModule;1.0.0: java.lang.IllegalStateException: impossible to publish myOrg#myModule;1.0.0!my-custom-jar.jar using local: no artifact pattern defined
I've managed to run my scenario and to resolve my issues using this tutorial There were two major issues in my code/integration.
First one is that you cannot tell Ivy to publish the artifacts in its repository without providing a path to it. I did this with the filesystem resolver:
<filesystem name="local" local="true" transactional="local">
<ivy pattern="${ivy.default.ivy.user.dir}/local/[module]/ivy-[revision].xml" />
<artifact pattern="${ivy.default.ivy.user.dir}/local/[module]/[artifact]-[revision].[ext]" />
</filesystem>
The stupid think about it is this should be build in. If you copy it as is, then everything works. If the config is different, or pointing to a different location - nothing works and you are not told why. I read tons of docs about Apache Ivy and it was nowhere mentioned that these patterns should point to the local Ivy repository. I thought these were the paths from where the jars should be taken. I actually complained about this, but the Ivy documentation is very confusing. Also I think the examples there are wrong. Who would like to publish the artifacts in their ivy.settings.dir. In my case this directory was in my repository!
There was a second issue. It is a smaller one and again very hard to see and fix. There's something wrong the revision param and again the documentation is messed up. If you specify one and the same string for the revision and pub revision the artifacts aren't publish without any explanation why. I fixed it by removing the revision from ivy.xml file.
Last, but not least, I didn't manage to run successfully the "thing" as Ant task, but with java -jar $IVY_JAR ... Maybe the issue was because of the versions, but I was too tired to try it with the fix.
P.S.#cantSleepNow thanks for the help.
You need to add artifact pattern to resolver in ivysettings.xml, something like (example from ivy documentation):
<ivysettings>
<resolvers>
<filesystem name="local" local="true">
<ivy pattern="${ivy.settings.dir}/1/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.settings.dir}/1/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
</ivysettings>

Keeping only the latest dependency snapshot using Ant and Ivy

I am using Ant to build my project and Ivy to resolve its dependencies. My project has a dependency which publishes snapshots to my internal Artifactory server.
If the dependency has released a new snapshot, and I do an <ivy:retrieve />, Ivy gets the new snapshot but keeps the previous snapshot around. So I have two versions of the dependency in my lib directory.
The dependency snapshots are named like depproject-1.0.0+23.jar where 23 is the build number. It is published at an address like http://artifactory.example.com/example-snapshots-local/com.example/depproject/1.0-SNAPSHOT/depproject-1.0.0+23.jar. This is not a Maven repository, and it is configured to store unique snapshots.
I am new to Ivy. Is this the expected behavior? How can I configure Ivy or Ant so that only the latest dependency snapshot is kept?
ivysettings.xml
<?xml version="1.0" encoding="UTF-8"?>
<ivy-settings>
<settings defaultResolver="main" />
<resolvers>
<chain name="main">
<ibiblio
name="artifactory-example-snapshots"
m2compatible="false"
root="http://artifactory.example.com/example-snapshots-local/"
pattern="[organization]/[module]/1.0-SNAPSHOT/[artifact]-[revision](-[classifier]).[ext]" />
<!-- more repos listed -->
</chain>
</resolvers>
</ivy-settings>
ivy.xml
<ivy-module version="2.0">
<info organisation="com.example" module="myproject" />
<dependencies>
<dependency org="com.example" name="depproject" rev="latest.integration" />
</dependencies>
</ivy-module>
I'm assuming you're using jars in the lib directory to create a classpath, something like:
<path id="compile.path">
<fileset dir="lib" includes="*.jar"/>
</path>
Your issue being multiple jars containing the same classes?
I think you have two options:
Use the ivy cachepath task to manage the build classpaths
Purge the lib directory, using he retrieve task to repopulate with the latest jars
The first option may appear more complicated, but it is actually a very powerful way to use ivy. For an example see:
How to avoid copying dependencies with Ivy

Ivy task 'install' not copying/installing documents

I am using ivy with ant to build multiple modules. I need to publish some documents (.docx files). But when I need to install from one ivy repository to other they are not being copied. How do I tell ivy to copy those documents when using install task.
Publications:
<publications>
<artifact name="find" type="jar" conf="core" />
<artifact name="Documentation" type="res" ext="docx"/>
<artifact name="Dep_report" type="res" ext="xml"/>
</publications>
Install task call to copy artifacts from one ivy repository to another:
<ivy:install organisation="${ivy.organisation}" module="${ivy.module}"
revision="${ivy.revision}" from="shared" to="released" overwrite="true" />
Also, I must add that publishing to shared and installing it to released ivy repository don't happen on the same ant call. I added < ivy:resolve /> before calling install and it didn't help either (Do I need to add any attributes to ivy:resolve call??). Do I need to specify dependency on the documentation in ivy.xml file? Install copies jar file and ivy.xml fine but not the docs or xml files. What am I missing? Any help is greatly appreciated.
Issue was not adding conf on artifacts. I needed to add conf="core" for both docx and xml file publication:
<publications>
<artifact name="find" type="jar" conf="core" />
<artifact name="Documentation" type="res" ext="docx" conf="core" />
<artifact name="Dep_report" type="res" ext="xml" conf="core" />
</publications>
Also, for ivy:install needed to add conf="core" as follows:
<ivy:install organisation="${ivy.organisation}" module="${ivy.module}"
revision="${ivy.revision}" from="shared" to="released" overwrite="true" conf="core" />

how to use the [ext] variable in ivy?

I want to use the url resolver to download depends. The depends are JS, or XML files. So, I used:
<url name="urlresolver">
<artifact pattern="http://[organisation]/[module]-[revision].[ext]" />
</url>
And
<ivy:retrieve pattern="${build}/[module]-[revision].[ext]"/>
the file is saved in .jar extension.
It's worth digging around the following ivy docs:
Terminology
Main Concepts
Best Practices
The first problem is that your url resolver is not configured to read ivy files for the remote modules (ignoring the first recommendation, in the ivy best practices, to use an ivy file with each module). Without module meta-data ivy will assume you're attempting to download JAR files.
A second problem is that you don't appear to be using an ivy repository to store your files. The following dependency declaration:
<dependency org="yourorg" name="module1" rev="9.1"/>
would be translated into the following URL, using your current settings:
http://yourorg/module1-9.1.jar
The "org" field is designed to specify the organisational unit publishing the module, not the server hostname.
I suspect that you're not really interested in building a repository of files and just want to persuade ivy to download and cache the files? In that case I'd recommend reading the following answer which is using extra attributes on the dependency artifacts to do something similar:
Resolving XSD's using Ivy
Example
ivy.xml
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
..
..
<dependency org="yourorg" name="yourmodule1" rev="9.1">
<artifact name="file1" e:hostname="www.server1.com" type="xml"/>
<artifact name="file2" e:hostname="www.server1.com" type="xml"/>
</dependency>
<dependency org="yourorg" name="yourmodule2" rev="9.1">
<artifact name="file3" e:hostname="www.server2.com" type="xml"/>
<artifact name="file4" e:hostname="www.server2.com" type="xml"/>
</dependency>
..
Note:
Each dependency declares the type of each artifact, plus the additional "hostname" attribute.
If the remote modules had ivy.xml, the publications section would alternatively store this artifact information.
Extra artifacts demonstrate ivy's power in enabling any sort of custom attribute meta-data.
ivysettings.xml
..
<url name="urlresolver">
<artifact pattern="http://[hostname]/files/[organisation]/[module]-[revision].[ext]" />
</url>
..
Demonstrates how the resolver makes use of both the standard attributes and the custom "hostname".

Ivy: how do I remove transitive dependencies?

I'm using Ivy to manage the dependencies on my project.
So far, I've specified a dependency on Hibernate and servlet-api. However, the hibernate jar itself has a lot of dependencies that aren't really needed, such as jaas and jacc.
This becomes a show-stopper because jaas and jaac are Sun libraries and therefore their licenses forbid to place them in the Maven repos, so Ivy can't find them there.
How do I make Ivy download Hibernate but not these two ?
As a bonus, if I actually needed those and downloaded their Jars from Sun, in which folder in my machine would Ivy look for them ?
Another option for not downloading any dependencies is to disable them with the transitive attribute. So if you wanted hibernate-core, but none of its dependencies, you could do this:
<dependencies>
<dependency org="org.hibernate" name="hibernate-core"
rev="3.3.1.GA" conf='..'
transitive="false" />
</dependencies>
How do I make Ivy download Hibernate but not these two?
Ivy does this using what it calls "configurations." Your ivy.xml that represents Hibernate will need to provide different configurations to represent different use-cases for hibernate. (There is obviously some use of hibernate that does require jaas and jacc, but apparently you don't make use of that case.)
Here is the documentation on configurations. If you want to provide the ivy.xml you are using for hibernate, I can provide pointers on building configurations that will remove the specific libraries you want removed.
If I actually needed those and downloaded their Jars from Sun, in which folder in my machine would Ivy look for them?
The "directories" that ivy looks in for ivy files and artifacts are specified by the list of resolvers you are using. The list of resolvers is specified in the ivy settings file (usually named ivysettings.xml.) Typically, these aren't local directories, but remote URLs. There is; however, a local-file resolver type that will work for this.
If you do this, you will need to provide both ivy files and the artifacts (jars), each with file-names that match the resolvers patterns. Details on that are in the documentation.
Here is an example local-file resolver from an ivy settings file:
<filesystem name="myfiles" checkconsistency="false" checksums="" transactional="false">
<ivy pattern="/data/repo/[organisation]/[module]-[revision].ivy.xml"/>
<artifact pattern="/data/repo/[organisation]/[module]-[revision].[ext]"/>
</filesystem>
Also note that you will need to point your ivy tasks to the correct resolver. You can do this with the resolver attribute on the ant tasks, or with the defaultResolver attribute on the settings element in the ivy settings file.
Here is the documentation on resolvers.
EDIT: The OP found a less-time intensive workaround for his specific original problem. The "exclude" child-tag of the dependency tag did the job for him:
<dependencies>
<dependency org="org.hibernate" name="hibernate-core" rev="3.3.1.GA" conf='..'>
<exclude name='jaas' />
<exclude name='jacc' />
</dependency>
</dependencies>
Browsing the web and blogs, I found the following ivy-settings to work at grabbing jaas/jacc and hibernate
<ivysettings>
<settings defaultResolver="chained" checkUpToDate="true" />
<resolvers>
<chain name="chained">
<url name="com.springsource.repository.bundles.release">
<ivy pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
<artifact pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
<url name="com.springsource.repository.bundles.external">
<ivy pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
<artifact pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
<ibiblio name="ibiblio" m2compatible="true"/>
<ibiblio name="jboss" root="http://repository.jboss.org/maven2/" m2compatible="true"/>
<ibiblio name="java-net-maven1" root="http://download.java.net/maven/1" pattern="${java.net.maven.pattern}" m2compatible="false"/>
<ibiblio name="java-net-maven2" root="http://download.java.net/maven/2/" m2compatible="true"/>
<ibiblio name="compass" m2compatible="true" root="http://repo.compass-project.org" />
</chain>
</resolvers>
The jboss ibibilio resolver is what did the trick at grabbing JAAS/JAAC
My ivy.xml then can then pull it in with
<ivy-module version="2.0">
<info organisation="foo" module="Bar"/>
<dependencies>
<dependency org="com.h2database" name="h2" rev="1.2+"/>
<dependency org="org.hibernate" name="hibernate-annotations" rev="3.4.0.GA"/>
</dependencies>
To answer your second sub-question literally, which nobody has done so far, "in which folder in my machine would Ivy look for JARs?" That depends. Assuming you haven't changed the location in ivysettings.xml or another configuration file: for JAAS,
this would be: (user home)/.ivy2/cache/javax.security/jaas/jars. If Ivy already unsuccessfully tried to find JAAS in the Maven Central or other repo's, that directory tree should already exist for the most part, and all you need to do is create the "jars" directory and place jaas-1.0.01.jar in it. Ivy will no longer complain about the missing dependency in its next invocation.
EDIT: Then again, see the discussion below to see considerations to not do it like this.
((user home) is C:/Users/(username) on Windows 7).

Resources