Ivy Dependency (pull in directory of files) - java

Extreme edit to question to have it make more sense:
Let's assume that I need to use a local version of httpclient rather than one that I can just pull from an online repo (due to signing reasons). The way that I want to handle this is like so...
ivy.xml
<dependencies>
...Other dependencies here
<dependency org="com.apache" name="httpclient" rev="4.2.2" conf="compile->default" ext="jar" />
</dependencies>
ivysettings.xml
<settings defaultResolver="central"/>
<resolvers>
<url name="repo">
<ivy pattern="http://myServer:8080/Repo/[organisation]/[artifact]/[revision]/ivy.xml" />
<artifact pattern="http://myServer:8080/Repo/[organisation]/[artifact]/[revision]/[artifact].[ext]"/>
</url>
<url name="httpclient">
<artifact pattern="http://myServer:8080/Repo/com.apache/httpclient/4.2.2/[artifact].[ext]"/>
</url>
<modules>
<module organisation="com.apache" resolver="repo" />
<module organisation="com.httpclient" resolver="httpclient" />
</modules>
Now what I'm hoping for here (and haven't been having much luck with) is the com.apache resolver looking for myServer:8080/Repo/com.apache/httpclient/4.2.2/ivy.xml and reading that, here's the contents of that file:
ivy.xml (in myServer:8080/repo/... directory)
<dependency org="com.httpclient" name="commons-codec" rev="1.6" />
<dependency org="com.httpclient" name="commons-logging" rev="1.1.1" />
<dependency org="com.httpclient" name="fluent-hc" rev="4.2.2" />
<dependency org="com.httpclient" name="httpclient" rev="4.2.2" />
<dependency org="com.httpclient" name="httpclient-cache" rev="4.2.2" />
<dependency org="com.httpclient" name="httpcore" rev="4.2.2" />
<dependency org="com.httpclient" name="httpmime" rev="4.2.2"/>
The reasoning behind wanting to read the second xml file rather than including the markup in my first file is pretty obvious when you consider how many LOC that would add to something that we include frequently. It also makes all future includes easier as well.
Right now the error that I'm getting is:
Some projects fail to be resolved
Impossible to resolve dependencies of com.myCompany#myProgramt;working#CompName
unresolved dependency: com.apache#httpclient;4.2.2: not found
Thanks for your help on this matter.

Ivy expects to find all the dependencies of a given artifact in the same resolver. So, it finds the artifacts for com.apache in your repo resolver, and expects to find com.httpclient in there as well.
Ivy also will roll through your <ivy pattern.../> and <artifact pattern.../> statements in order within the same resolver declaration. You can use this to your advantage to create a single resolver which hits both repositories in the order you want:
<url name="amalgamation">
<ivy pattern="http://myServer:8080/Repo/[organisation]/[artifact]/[revision]/ivy.xml" />
<artifact pattern="http://myServer:8080/Repo/[organisation]/[artifact]/[revision]/[artifact].[ext]"/>
<artifact pattern="http://myServer:8080/Repo/com.apache/httpclient/4.2.2/[artifact].[ext]"/>
</url>

When you configure your build to use the following resolver
<ibiblio name="central" m2compatible="true"/>
You are telling ivy to download its dependencis from Maven Central
What is your objective here? To create a local ivy repo that functionally works like Maven Central? In that case the simplest solution would be to setup a Maven repository manager like: Nexus, Artifactory or Archiva. A maven repository manager can act like a smart cache and "proxy" jars stored in the Central Maven repo.
Configuring your build to use a local Maven Repository is easy:
<ibiblio name="central" m2compatible="true" root="http://hostname:portnum/MavenRepo/>

What server are you using for your remote JAR repository?
Both Nexus and Artifactory can be setup to pull jars stored locally on themselves before puling ones from the remote repository. This way, you don't have to munge your ivysettings.xml. Instead, you simply download your preferred versions of the jars on Artifactory/Nexus. And, both are free, open source, downloads. It's way easier to do what you want with Artifactory/Nexus than futzing with your Ivy settings.
By the way, I have a Ivy project in Github you might want to look at. You simply attach this project to your Ant project, and it has everything automatically configured for Ivy. This way, an entire site can use Ivy for all of their projects, and everything is centrally controlled.

Related

IVY Build, how do I use an extlib directory in the project?

There are several jar files, which are from a COTS product that we keep in our project's "extlib" folder at the root of the project. I want to have these included in ivy, but not put in the repository, just read from the project/extlib folder. Is this possible or do I need to add them to the artifactory?
Create an ivy settings file with the following content:
<ivysettings>
<settings defaultResolver='artifactory' />
<resolvers>
<ibiblio name='artifactory' m2compatible='true' root="http://my.artifactory.server"/>
<filesystem name='local'>
<artifact pattern='${ivy.settings.dir}/extlib/[artifact]' />
</filesystem>
</resolvers>
<modules>
<module organisation='NA' resolver='local' />
</modules>
</ivysettings>
And declare your dependencies as follows:
<dependencies>
<dependency org='org.apache.tomcat' name='tomcat-api' rev='7.0.21' />
..
..
<dependency org='NA' name='myspecial.jar' rev='NA' />
</dependencies>
The special "NA" organisation is configured to pull files from the "extlib" directory. The revision attribute is manadatory but generally meaningless when referring to files stored within the project directory.

How to publish native libraries with Ivy?

For Java library projects, the artifact to publish is straightforward since the output is a single jar file. However, I also have a project with the following stuff to publish:
MyLib.jar
armeabi/libStuff.so
armeabi-v7a/libStuff.so
mips/libStuff.so
x86/libStuff.so
I cannot setup all those .so files as artifacts, since they all have the same name. What is the recommended way to go? Put everything in a zip and let users use gradle (or ant or whatever) to unzip it prior to the build? Should I put the Jar file aside from the zip? Is there a convention for such artifacts?
The best way with Ivy to manage many "same" artifact which only difference is the architecture, is to use extra attributes.
So in your module you would declare:
<publications xmlns:e="http://ant.apache.org/ivy/extra">
<artifact name="MyLib" type="jar" ext="jar" />
<artifact name="libStuff" type="native" ext="so" e:arch="armeabi" />
<artifact name="libStuff" type="native" ext="so" e:arch="armeabi-v7a" />
<artifact name="libStuff" type="native" ext="so" e:arch="mips" />
<artifact name="libStuff" type="native" ext="so" e:arch="x86" />
</publications>
The drawbacks is that your entire chain around Ivy would have to take that extra attribute into account. For instance, you should be able to configure your repository so it would accept a custom pattern like this one:
${repository.dir}/[organisation]/[module]/[arch]/[revision]/[artifact].[ext]
Another solution, as you mentioned, is to work with a zip folder. And this may be a good timing since Ivy 2.4 which is just about to be released, is supporting zipped folder via packaging.
For instance you could declare:
<publications xmlns:e="http://ant.apache.org/ivy/extra">
<artifact name="MyLib" type="jar" ext="jar" />
<artifact name="libStuff" type="natives" ext="zip" packaging="zip" />
</publications>
Then Ivy will download a libStuff-1.2.3.zip into its cache and will automatically unzip it into the cache to libStuff-1.2.3, folder in which you could find your several natives libraries.

How do I include an Ivy Dependency in subversion repo

So, since I've been unable to find a way to resolve our dependency issues by including everything from external sources I've turned to Eclipse / IvyDE for ant / Ivy integration.
With that said, I normally include a lib like this:
<dependency org="org.jsoup" name="jsoup" rev="1.6.3"/>
However what if I want to look at something in our own intranet?
Example, if the folder holding the jar is somewhere like this:
https://prdsvn01.company.intra.net/repo/libName/
and I want to include lib.jar into my folder.
I've been relatively unable to find ivysettings.xml in this implementation of eclipse, nor am I confident that I'd be able to get it right if I could.
Could someone help me with this?
The following ivy settings file:
<ivysettings>
<settings defaultResolver="central"/>
<resolvers>
<ibiblio name="central" m2compatible="true"/>
<url name="my-repo">
<artifact pattern="http://myserver/myrepo/[organisation]/[artifact]/[revision]/[artifact].[ext]"/>
</url>
</resolvers>
<modules>
<module organisation="org.mycompany" resolver="my-repo"/>
</modules>
</ivysettings>
Is configured to retrieve artifacts from Maven Central by default, and local artifacts from a HTTP server.
Update
ivy.xml
Nothing special in the ivy file. Just declare the dependencies and which configuration to associate them with:
<configurations>
<conf name="compile" description="Required to compile application"/>
</configurations>
<dependencies>
<!-- compile dependencies -->
<dependency org="org.slf4j" name="slf4j-api" rev="1.6.4" conf="compile->default"/>
<dependency org="org.mycompany" name="my-module" rev="1.0" conf="compile->default"/>
</dependencies>
Note:
It's ivy best practice to use configurations.
build.xml
<target name="resolve" dependencies="Resolve build dependencies">
<ivy:resolve/>
<ivy:report todir='build/reports' graph='false' xml='false'/>
<ivy:cachepath pathid="compile.path" conf="compile"/>
..
</target>
Notes:
The ivycachepath task transforms an ivy configuration into a populated ANT classpath. Very useful.
The ivy report task tells you the jars on the classpath(s)
Ivy resolve build output
All the magic is in the settings file. Running the build produces the following:
[ivy:resolve] found org.slf4j#slf4j-api;1.6.4 in central
[ivy:resolve] found org.mycompany#my-module;1.0 in my-repo
..
[ivy:resolve] downloading http://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.6.4/slf4j-api-1.6.4.jar ...
..
[ivy:resolve] downloading http://myserver/myrepo/org.mycompany/my-module/1.0/my-module.jar ...
Notes:
The my-repo resolver is used for modules with a "org.mycompany" groupId.
Everything else comes from the default resolver, Maven Central.

Convert ivy.xml to pom.xml

I have a ivy.xml - https://gist.github.com/1898060
I also have the jar file related to this ivy.xml.
What i need is a mechanism to import this project to my maven repo and use it in my maven project.
SO basically if i am able to convert the ivy.xml to pom.xml , i might be able to get it work.
Is there some mechanism through which i can achieve this.
I am looking for something like a maven plugin to accomplish this task.
I know that there are ways we can edit the ivy.xml and build.xml to achieve this but then i dont want to do it , as the project is in a private repo.
What you really need to do is publish the jars built by ANT project into your Maven repository.
ant -Dproject.version=0.9.0-local-20120211095554 clean publish
I know you don't want to change the ANT build, but creating an extra "publish" target will properly integrate your ANT and Maven projects.
The two jar artifacts, published by your modified ANT build, could be consumed normally as follows:
<dependency>
<groupId>com.opengamma</groupId>
<artifactId>og-analytics</artifactId>
<version>0.9.0-local-20120211095554</version>
</dependency>
<dependency>
<groupId>com.opengamma</groupId>
<artifactId>og-analytics</artifactId>
<version>0.9.0-local-20120211095554</version>
<classifier>sources</classifier>
</dependency>
Modifications to your ANT build
ivy.xml
Main changes are to your publications section:
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
<info organisation="com.opengamma" module="og-analytics"/>
<publications>
<artifact name="og-analytics" type="jar"/>
<artifact name="og-analytics" type="pom"/>
<artifact name="og-analytics" type="jar" e:classifier="sources"/>
</publications>
<dependencies>
<dependency name="og-util" rev="0.9.0-local-20120211095525" revConstraint="latest.integration"/>
<dependency org="org.jfree" name="jfreechart" rev="1.0.13"/>
<dependency org="cern" name="colt" rev="1.2.0"/>
<dependency org="cern" name="parallelcolt" rev="0.9.1"/>
<dependency org="latexlet" name="latexlet" rev="1.11"/>
<dependency org="org.apache.commons" name="commons-math" rev="2.1"/>
<dependency org="it.dexy" name="json-doclet" rev="0.3.1"/>
<dependency org="org.json" name="simple" rev="1.1"/>
<exclude org="org.junit"/>
</dependencies>
</ivy-module>
Notes:
The ANT project will now publish 3 files, jar, sources jar and the Maven POM
In Maven source jars have a "classifier" attributes that is set to "sources" (Not source). To facilitate this we're adding an ivy extra attribute.
No need for version and status information in the info tag header. This will be added by the publication step.
build.xml
<target name="prepare" description="Generate POM">
<fail message="Unset property: project.version" unless="project.version"/>
<ivy:deliver deliverpattern="${build.dir}/ivy.xml" pubrevision="${project.version}" status="release"/>
<ivy:makepom ivyfile="${build.dir}/ivy.xml" pomfile="${build.dir}/${ivy.module}.pom"/>
</target>
<target name="publish" depends="build,prepare" description="Upload to Nexus">
<ivy:publish resolver="nexus-deploy" pubrevision="${project.version}" overwrite="true" publishivy="false" >
<artifacts pattern="${build.dir}/[artifact](-[classifier]).[ext]"/>
</ivy:publish>
</target>
Notes:
The deliver task is optional, but recommended in case your ivy file contains dynamic revisions, such as "latest.release" or "latest.integration".
The makepoms task has powerful support for convert ivy configurations into Maven scopes. Does not apply in your case, but an incentive to learn more about ivy :-)
The publish task uses a specified pattern to find files specified in ivy's publications section.
ivysettings.xml
This is where you configure the location of the repositories and credentials to be used by publish build target.
<ivysettings>
<settings defaultResolver="nexus-central"/>
<credentials host="somehost" realm="Sonatype Nexus Repository Manager" username="????" passwd="????"/>
<resolvers>
<ibiblio name="nexus-central" root="http://somehost/nexus/content/repositories/central/" m2compatible="true"/>
<ibiblio name="nexus-deploy" root="http://somehost/nexus/content/repositories/repo" m2compatible="true"/>
</resolvers>
</ivysettings>
Notes:
Ivy downloads use the configured default resolver nexus-central.
The ivy publish task pushes to the Nexus repository called nexus-deploy
The security realm in this example matches Nexus Maven. Would be different for other repo managers.
Apache Ant itself provides a task to do this - makepom. Always helps to consult the documentation!

How does Apache Ivy resolve the variables in artifact patterns provided in the ivysettings.xml file?

If my ivysettings.xml file includes:
<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>
And my ivy.xml file includes:
<dependency org="org.junit"
name="com.springsource.org.junit"
rev="4.4.0" />
From when I ran Ivy, I can tell that this resolves to: http://repository.springsource.com/ivy/bundles/external/org.junit/com.springsource.org.junit/4.4.0/com.springsource.org.junit-sources-4.4.0.jar
So the resolutions go:
[organization] => "org.junit"
[module] => "com.springsource.org.junit"
[revision] => "4.4.0"
[artifact] => "com.springsource.org.junit-sources"
[ext] => "jar"
I see how ivy resolves the [organisation], [module], and [revision] in the URL pattern (duh), but how does it resolve [artifact] and [ext]?
The documentation on the URL resolver seems to be lacking.
Ivy first resolves the <ivy pattern... />, with the organization, module, and revision given, and with the [artifact] hardcoded as "ivy" and [ext] hardcoded as "xml". This yields a URL, in this case:
http://repository.springsource.com/ivy/bundles/external/org.junit/com.springsource.org.junit/4.4.0/ivy-4.4.0.xml
This is the ivy configuration file for this module. Among other things, this ivy configuration file contains information about other artifacts, in particular:
<artifact name="com.springsource.org.junit-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
These two are then used to complete the <artifact pattern... /> part - to download the license and to download the jar file.

Categories