Add Jars to Grails Project Using Ivy - grails

I'm following the Grails Mail tutorial: http://grails.org/A+simple+EmailerService and it mentions "Then copy two jar files into the application local lib: activations.jar and mail.jar.". Though I can do the manual copy, I was wondering if there's some way I could update my Ivy configuration file to do that pulling automatically instead. I'm not familiar enough with Ivy at this point to know how to look for repositories, etc..

First of all you need to install the ivy plugin:
grails install-plugin ivy
Then you can configure your ivy.xml:
<ivy-module version="2.0">
<info organisation="apache" module="hello-ivy"/>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.0"/>
<dependency org="commons-cli" name="commons-cli" rev="1.0"/>
</dependencies>
</ivy-module>
Finally, invoke the grails get-dependencies command.
The jars will then be downloaded in the project's lib directory.

It depends on where you get your jars from. For info on Ivy and how it deals with dependencys see this link. http://www.ibm.com/developerworks/java/library/j-ap05068/index.html

Related

How to retrieve artifacts with per specific patterns using ant ivy

I have a huge dependency which exports a number of dependencies. I wish to restrict my retriev to couple of them. The pattern is [artifact]-[revision].[ext].
How do i specify this in ivy:retrieve task call
Configurations in ivy is the mechanism for controlling groups of dependencies within ivy.
Once these configurations have been setup in your ivy file it becomes simple to retrieve them within your ANT build as follows:
<ivy:retrieve pattern="lib/[artifact].[ext]" conf="my_custom_conf"/>
Perhaps you could supply some more details of what you want to achieve and someone can demonstrate how to setup a configuration for this purpose. (I'd also recommend searching the Stackoverflow ivy tag, for other examples)
Update
If an ivy module publishes more than one artifact it's possible to restrict the dependency in your ivy file as follows:
ivy.xml
<configurations>
..
<conf name="archives" description="Configuration containing only archive files"/>
</configurations>
<dependencies>
..
<dependency org="acme" name="foo" rev="2.0" conf="archives->default">
<artifact name="a1" type="tar"/>
<artifact name="an" type="zip"/>
</dependency>
</dependencies>
Alternatively..
Look into the remote modules's ivy.xml. There may already be a configuration setup for these files, in which case it becomes a lot simpler (because it's been pre-setup)
<dependency org="acme" name="foo" rev="2.0" conf="archives->remotearchives"/>
The "conf" part of the dependency is mapping the remote configuration onto your local one.

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".

How to build a Grails Plugin and deploy it to local Ivy repository?

Is there a way to build a Grails Plugin and deploy the artifacts to the local Ivy repository?
With Maven, I would do this:
mvn install
Use the ivy publish task
<ivy:publish resolver="local" pubrevision="1.0">
<artifacts pattern="build/[artifact].[ext]" />
</ivy:publish>
Note 1
Your ivy file must list the artifacts you plan to publish
<ivy-module version="2.0">
<info organisation="myorg" module="mymodule"/>
<publications>
<artifact name="mymodule" type="zip"/>
</publications>
</ivy-module>
Maven derives this information from the module declaration in the POM file. One of the advantages of using ivy is that you can publish more than one artifact.
Note 2
The ivy local repository is located in the following location by default:
${user.dir}/.ivy2/local
You can of course create your own custom repositories by declaring alternative resolvers in you settings file

Apache Ivy: resolving dependencies embedded in an installer

I have a problem with a build where I have to resolve non-standard artifacts through Apache Ivy.
Problem:
I have dependencies on two artifacts (a.jar and a-lib.jar).
The two dependencies come only as part of a single installer (a_installer.jar).
The installer can be downloaded, the embedded artifacts themselves not.
It's possible to manipulate the installer to unpack the needed dependencies.
Requirements:
I have to resolve/download the artifacts during the build (I cannot keep the installer or the extracted artifacts with my code).
I cannot use a repository to store the extracted artifacts.
Subclassing/Extending Ivy/whatever is perfectly fine.
Has anyone solved a similar problem, or some helpful information to share?
Or maybe I'm approaching the problem in the wrong way? From what I found so far on the web, people seem to use Ivy just to download files and post-process them manually (with Ant/whatever) after the fact, and not actually resolving more complicated dependencies within Ivy.
Thanks
PS: I don't care whether the installer is also put into the ivy download cache, but I would like to download the installer only one time (and not for both dependencies).
The problem with a call to "ivy:retrieve" is that you need to also add an "artifact" tag in your ivy.xml (complete with URL) in order to retrieve a dependency not found in a Maven respository...
I don't like this for two reasons
The ivy.xml should just declare your dependencies, not their locations.
Need additonal custom logic in the build.xml to handle the 3rd party package
Ideally it should be your repository settings that decide how to download the various jars, that is why I like the packager resolver. Even if the library I want is not in Maven, I can configure ivy to handle it.
The following is an example of turning the jreleaseinfo project into an ivy dependency (hosted in sourceforge, I couldn't find it in Maven)
ivy.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="ivy_packager"/>
<dependencies>
<dependency org="ch.oscg" name="jreleaseinfo" rev="1.3.0"/>
</dependencies>
</ivy-module>
Declare two resolvers. Default is Maven2, the other is a packager configured to look locally for instructions. (See also the Ivy Roundup project)
ivysettings.xml
<ivysettings>
<settings defaultResolver="maven2"/>
<resolvers>
<ibiblio name="maven2" m2compatible="true"/>
<packager name="repackage" buildRoot="${user.home}/.ivy2/packager/build" resourceCache="${user.home}/.ivy2/packager/cache">
<ivy pattern="file:///${basedir}/repository/[organisation]/[module]/[revision]/ivy.xml"/>
<artifact pattern="file:///${basedir}/repository/[organisation]/[module]/[revision]/packager.xml"/>
</packager>
</resolvers>
<modules>
<module organisation="ch.oscg" name="jreleaseinfo" resolver="repackage"/>
</modules>
</ivysettings>
The magic is containing in the "packager" file. At resolve time this will be used to generate an ANT script that both downloads and extracts the required jars.
(No need to put this logic into your build.xml)
repository/ch.oscg/jreleaseinfo/1.3.0/packager.xml
<packager-module version="1.0">
<property name="name" value="${ivy.packager.module}"/>
<property name="version" value="${ivy.packager.revision}"/>
<property name="zipname" value="${name}-${version}"/>
<resource dest="archive" url="http://sourceforge.net/projects/jreleaseinfo/files/jreleaseinfo/jreleaseinfo%201.3.0/jreleaseinfo-1.3.0.zip/download" sha1="9386d92758e627d04c2480b820731fd538b13a3f" type="zip"/>
<build>
<move file="archive/${zipname}/${zipname}.jar" tofile="artifacts/jars/${name}.jar"/>
</build>
</packager-module>
To reduce the number of files I omitted the module's ivy.xml. This appears to be optional unless you want to declare it's licence and other attributes that should be present in a public repository.
I think this is very straightforward: 'ivy:retrieve' a_installer and then unzip a.j and a-lib into your lib directory (or wherever you want it). This should be easily to do with ant?
I have to wonder if there is some complication you haven't mentioned that prevents you from doing this.

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