Ivy Use Cases
What is this page about?
This page demonstrate common and possible uses of Ivy. The main usage is of course bringing Java JAR files to a project but there may be other interesting use cases.
The most common use cases
The following use cases are very common and are going after Apache Maven's spirit.
- (The trivial one Find and bring Java JAR files needed to compile a Java project. (Known as "compile" dependency.)
- (Almost trivial as the above) Declare the runtime dependencies of a Java product in other Java JAR files. (Known as "runtime" dependency.)
- Find and bring Java JAR files needed for unit test, usually during an automatic build. (Known as "test" dependency.)
Note: these kind of dependencies (AKA 'configurations') are widely used by free open source projects around. Other kinds of dependencies are not standard and are used (or may be used) mostly internally by organizations.
Other possible and interesting use cases
- Web service WSDL versioning. The idea here is to create a project ('module') containing WSDL and probably XSD files needed to define a web-service. The need to version WSDL documents comes mainly during parallel development of a web-service and its client. They both depends on the WSDL document and have to explicitly know if they are using the same interface - the WSDL document. Note: This use case could be generalized as "interface versioning". It is good not only for WSDL but also to CORBA IDL, and alike.
- Build time properties. During the build, we often need to use common properties that are the same among all the projects. For example: we want to add Vendor-Name and Vendor-URL to the JAR manifest; or we want to auto-generate Java code from XML schema with a common set of XML-namespace-to-Java-package-name mapping. For such uses, we can create an ivy module that other projects depends on, and automatically share these properties in a simple way. This is better than just using a properties file that is located 'somewhere around' (or worst: a file that is being duplicated of each and every project) since we use versioning. Using ivy.xml you can instantly know what exact version of the properties file your module had been built against. This dependency, of course, need to be declared using a separate 'configuration' in ivy.xml, in order not to be confused with the 'compile' and 'runtime' configurations.
- Non-code dependencies XML Schema (XSD files) are one of the many other formats that let you import a file to another file. The problem starts when you have some common base artifacts that are being used by higher level artifacts. For example: you have XML schemas for the infrastructure, and you have application specific XML schema for every application. You want to import the common infrastructure XSD file into your application's XSD file. The assumption is that you don't want to duplicate code or use symbolic links. You want to know what exact version of the infrastructure you have imported to your XSD file. One possible solution (without using Ivy) is to add the version name to the XSD file, and to use that version-explicit file name in the 'import' element of the application's XSD file. But in such solution you stick to a fixed version and cannot benefit from the 'latest' features of Ivy. Ivy's way would be to create a separate module for the infrastructure XSD (same as in section 2.1) with its own ivy.xml, and a separate module (+ ivy.xml) for any application depending on it. The applications can define 'latest.<something>' in the 'rev' attribute and will automatically get the latest infrastructure XSD file. After publish, the ivy.xml would explicitly indicate what exact version of the infrastructure XSD has been used. If you are going to implement this technique, you will probably rich to the following problem: what path+filename to write in the 'import' element of the application XSD file.
For example: before you considered Ivy, you had in the same directory: infrastructure.xsd and app.xsd. app.xsd imports 'infrastructure.xsd' without any additional path info, since they are both at the same directory. Another application: 'super-app' want to import 'app.xsd' along with its dependencies (infrastructure.xsd). With duplication, you simple copy 'app.xsd' and 'infrastructure.xsd' to 'super-app' XSD directory. Let's see how Ivy can help.
With Ivy, you define in ivy.xml of 'app' a "schema" configuration pointing to 'infrastructure' module. To use it, you 'ivy:retrieve' the infrastructure.xsd file to 'schema/imported' directory of 'app' project. 'app' project's own schema called 'app.xsd' sits in 'schema/src' directory. Hence, in 'app.xsd' you import '../imported/infrastructur.xsd' file. Notice the relative path. In 'super-app' ivy.xml you define a configuration "schema" depends on 'app' module. The same 'ivy:retrieve' brings both 'infrastructure.xsd' and 'app.xsd' to 'schema/imported' of 'super-app' project tree. 'super-app' project's own schema sits in 'schema/src' as before and importing '../imported/app.xsd' that itself imports '../imported/infrastructure.xsd'.
See the Ivy magic? Using retrieve and relative path in XSD import, you can benefit Ivy's dependency management on XML Schema artifacts!
(Note: I'll be glad if someone would be able to rewrite this section in better words... easyproglife.)
Other use cases
Note: if you are using Ivy in a different way, please share us all. The benefit would be to all of us: we would better understand what other people expect Ivy to do, and we may together develop common 'usage patterns' to address common problems in a common, easy and simple way.
remarks by Andreas Sahlbach
IMHO Ivy has to fulfill two requirements:
- resolve (transitive) dependencies for my project
- help me to manage my repositories
1) will not work without 2). I need a controlled way to access my repositories. I need to be able to get stuff from repositories (dependencies, my own build results, information about resolves) and I need to be able to put stuff into repositories (again: dependencies and my build results). All this needs to be usable from ant, so that I can put it altogether in a neat ant script (for the "dressed apes" that are going to use my ant script at the end). Examples:
- We use several repositories depending in which environment we are currently developing (inside the intranet / outside the intranet / offline). I need to have a way to copy all dependencies of my project to my local repository so I can plug off the network cable and can still build everything.
- For a deployment ant target I want to retrieve the "latest.whatever" from my enterprise repository with all its dependencies. I am using ivy:install for that right now, but ivy:install needs ivy:resolve to work properly. This is pretty annoying, because I don't need to "resolve" my 47 dependencies just for the deployment task. Additional comment: I just noticed that I am still cheating here, actually there is no way to ask ivy to get the results of an ivy build from the repository. What I would like to do is an ivy:retrieve with a specific configuration of my own artifact (not of my dependencies). To say it by example: My build produces a public API in form of a jar and a server application in form of an ear or war. My build should put everything into the enterprise repository and in the following deploy task, it should be able retrieve the war or ear file so I can copy it into the webapps dir or something.
- I need a clean way to put an additional dependency into the repository so again I can put it into a neat ant script. Again I am doing this with groovy magic and the ivy:install task, but here again ivy:resolve is needed so Ivy knows about my repositories. This also means that the installation of an additional 3rd party dependency will fail if the resolve process fails (prolly because it is lacking the very same dependency I am just trying to install with this task)
- ivy should help the user in the task to create ivy-files. Maybe by presenting a basic form that the user can fill out and providing a fresh ivy.xml as a template for further editing
My $0.02 end here. Andreas Sahlbach