How to use Ivy + IvyDE in eclipse to put different jars in lib and web-inf/lib

shawnjohnson picture shawnjohnson · Aug 14, 2013 · Viewed 7.8k times · Source

So, I'm trying to add Ivy to my project, which outputs a WAR file. Some dependencies, like RESTEasy and Jackson are available at runtime in JBoss, so I don't want those in my war/WEB-INF/lib folder. Others libraries are not available via JBoss modules, so I want to include those in my project.

** NOTE: In eclipse, I'm using the Dynamic Web Module facet. The idea is to get IvyDE to copy the desired runtime dependencies into war/WEB-INF/lib.

Initially I created 2 ivy configuration files:

  • ivy.xml - runtime (not included in WAR)
  • ivy_web.xml - include in war

Then I used the GUI to configure the IDE equivalent of the Ant retrieve task. So, in my ANT build file, which I don't really want to use in my IDE, I have the following:

<ivy:retrieve pattern="war/WEB-INF/lib/[artifact]-[revision].[ext]" file="ivy-web.xml" type="jar" />
<ivy:retrieve pattern="lib/[artifact]-[revision].[ext]" file="ivy.xml" type="jar" />
  • image not allowed yet :-(

I noticed in another post comment (mapping multiple ivy files in Eclipse) they mention using only 1 ivy.xml - but I'm not quite sure how to get there?

Oh, I also noticed this as well: IvyDE + WTP: How to workaround that ivy library is ignored by WTP? - however my project doesn't use the right kind of facets, and I'd rather not add them.

So, after reading this (https://stackoverflow.com/a/16575318/880884) post, I added compile and runtime configurations to my project. It looks about like this:

<configurations>
    <conf name="compile" description="used for building"/>
    <conf name="runtime" description="used for running"/>
</configurations>

 <dependencies>
    <!-- compile -->
    <dependency org="org.codehaus.jackson" name="jackson-core-asl" rev="1.9.2" conf="compile->default"/>
    <dependency org="org.codehaus.jackson" name="jackson-xc" rev="1.9.2" conf="compile->default"/>
    <dependency org="org.codehaus.jackson" name="jackson-jaxrs" rev="1.9.2" conf="compile->default"/>


    <!-- runtime -->
    <dependency org="com.google.guava" name="guava" rev="14.0.1" conf="runtime->default"/>
    <dependency org="com.google.inject" name="guice" rev="3.0"  conf="runtime->default"/>
    <dependency org="aopalliance" name="aopalliance" rev="1.0" conf="runtime->default"/>
    <dependency org="javax.inject" name="javax.inject" rev="1" conf="runtime->default"/>
</dependencies>

Again, I tried to add just the one ivy.xml. Next I went the Project properties > Ivy > Retrieve List > Add - Added 2 different configurations, one for compile, which maps to /lib. The other uses the 'runtime' configuration and specifies "war/WEB-INF/lib/[artifact]-[revision].[ext]" for the retrieve pattern.

However, I end up with the "compile" in my war/WEB-INF/lib/, which is NOT what I wanted. I ONLY want the runtime dependencies copied there.

Answer

Mark O&#39;Connor picture Mark O'Connor · Aug 14, 2013

I think the bit you're missing is the use of configurations, in the retrieve task:

<ivy:retrieve pattern="lib/[artifact]-[revision].[ext]" conf="compile" />

Configurations are ivy's mechanism to group dependencies together.

Example

├── build.xml
├── ivy.xml
└── target
    ├── lib
    │   ├── jackson-core-asl-1.9.2.jar
    │   ├── jackson-jaxrs-1.9.2.jar
    │   ├── jackson-mapper-asl-1.9.2.jar
    │   └── jackson-xc-1.9.2.jar
    ├── reports
    │   ├── ivy-report.css
    │   ├── myorg-mymodule-compile.html
    │   └── myorg-mymodule-runtime.html
    └── war
        └── WEB-INF
            └── lib
                ├── aopalliance-1.0.jar
                ├── asm-3.1.jar
                ├── cglib-2.2.1-v20090111.jar
                ├── guava-14.0.1.jar
                ├── guice-3.0.jar
                └── javax.inject-1.jar

build.xml

<project name="demo" default="retrieve" xmlns:ivy="antlib:org.apache.ivy.ant">

   <property name="build.dir" location="target"/>

    <target name="resolve" description="Use ivy to resolve dependencies">
        <ivy:resolve/>
        <ivy:report todir='${build.dir}/reports' graph='false' xml='false'/>
    </target>

    <target name="retrieve" depends="resolve" description="Populate directories">
      <ivy:retrieve pattern="${build.dir}/lib/[artifact]-[revision].[ext]" conf="compile" />
      <ivy:retrieve pattern="${build.dir}/war/WEB-INF/lib/[artifact]-[revision].[ext]" conf="runtime" />
    </target>

    <target name="clean" description="Cleanup build files">
        <delete dir="${build.dir}"/>
    </target>

    <target name="clean-all" depends="clean" description="Additionally purge ivy cache">
        <ivy:cleancache/>
    </target>

</project>

Notes:

  • The example above also generates a dependency resolution report, which I find very useful for seeing the content of each configuration.

ivy.xml

<ivy-module version="2.0">
  <info organisation="myorg" module="mymodule"/>

  <configurations>
    <conf name="compile" description="used for building"/>
    <conf name="runtime" description="used for running"/>
  </configurations>

  <dependencies>
    <!-- compile -->
    <dependency org="org.codehaus.jackson" name="jackson-core-asl" rev="1.9.2" conf="compile->default"/>
    <dependency org="org.codehaus.jackson" name="jackson-xc" rev="1.9.2" conf="compile->default"/>
    <dependency org="org.codehaus.jackson" name="jackson-jaxrs" rev="1.9.2" conf="compile->default"/>

    <!-- runtime -->
    <dependency org="com.google.guava" name="guava" rev="14.0.1" conf="runtime->default"/>
    <dependency org="com.google.inject" name="guice" rev="3.0" conf="runtime->default"/>
    <dependency org="aopalliance" name="aopalliance" rev="1.0" conf="runtime->default"/>
    <dependency org="javax.inject" name="javax.inject" rev="1" conf="runtime->default"/>
  </dependencies>
</ivy-module>