How to copy runtime libraries without the provided ones in IVY - ivy

I thought I wouldn't need to ask this but I am not having any progress.
The solution to this question:
How are maven scopes mapped to ivy configurations by ivy actually addresses question but in its theoretical part.
I have this configuration:
<conf name="compile" description="???" />
<conf name="runtime" description="???" extends="compile" />
<conf name="test" description="???" extends="runtime" />
<conf name="provided" description="???" />
Assume I have this dependency:
<dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" transitive="false" />
What I want is: when I invoke the ivy:retrieve to copy the libraries to the .war lib directory before bundling it, I want only to copy all runtime (and compile implicitly) but no servlet-api.
so how to use ivy:retrieve then?
<ivy:retrieve conf="WHAT_TO_PUT_HERE" />
and how to configure the dependency:
<dependency conf="WHAT_IS_THE_CONF_MAPPING" org="org.apache.tomcat" name="servlet-api" rev="6.0.16" transitive="false" />
I'm plateauing here, so please any help would be appreciated.
Knowing that the ivy.xml for servlet-api defines the artifact with
conf="master"
So I think the question is how to 'really' map Provided scope of maven to the provided configuration of IVY.

This is how you map a dependency onto the local "provided" configuration:
<dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" conf="provided->master"/>
The configuration mapping works as follows:
provided->master
^ ^
| |
Local Remote
config config
As explained in the answer the special "master" configuration contains only the artifact published by this module itself, with no transitive dependencies:
How are maven scopes mapped to ivy configurations by ivy
This means the "transitive=false" attribute is not required.
Update
How you use the configuration is up to you. The first option is simpler, but I prefer the second approach because my configuration reports match my classpath contents
Option 1
You can create a single classpath as follows:
<ivy:cachepath pathid="compile.path" conf="compile,provided"/>
This can then be used in the javac task as follows:
<javac ... classpathref="compile.path">
..
Option 2
Or I prefer to have a one-2-one mapping between configurations and classpaths:
<ivy:cachepath pathid="compile.path" conf="compile"/>
<ivy:cachepath pathid="provide.path" conf="provided"/>
The problem with the latter approach is that the javac task need to have the classpath usage explicitly stated as follows:
<javac ...
<classpath>
<path refid="compile.path"/>
<path refid="provided.path"/>
</classpath>
I think this explicitly explains how you use this special provided scope, but it's really up to you.

Related

Why does Artifactory require an explicit artifact for some Ivy dependencies

I have an Artifactory server that I use to resolve Ivy dependencies. When I want to add a dependency to my ivy.xml, I sometimes have to add an explicit nested <artifact> tag, and I don't understand why.
Example A:
<dependency org="com.google" name="guava" rev="[7,)" conf="compile,runtime" />
Example B
<dependency org="com.twelvemonkeys.common" name="common-image" rev="3.0.1" conf="compile,runtime">
<artifact name="common-image" ext="jar"/>
</dependency>
Looking at the cached dependencies in the Artifactory tree view, there's nothing that indicates that the last example should need extra info to resolve the dependency, but Artifactory suggests it itself, and the resolution doesn't work without out.
I'm using Ivy against a repository with Maven layout. My settings where generated by Artifactory and look something like:
<?xml version="1.0" encoding="UTF-8"?>
<ivy-settings>
<settings defaultResolver="main" />
<resolvers>
<chain name="main">
<ibiblio
name="public"
m2compatible="true"
root="http://example.org/artifactory/remote-repos" />
</chain>
</resolvers>
</ivy-settings>
Why does Artifactory require an explicit artifact for some Ivy dependencies and not for others?
Edit 20151005: Added Ivy settings example
The tool performing the dependency resolution is the Ivy client and not Artifactory.
Based on the dependency deceleration the Ivy resolver decides which artifact to request from the repository (in your case it is Artifactory).
The artifact feature provides more control on a dependency for which you do not control its ivy file.
It enables to specify the artifacts required, if the dependency has no ivy file.
For more information about the artifact feature and when it should be used consult the Ivy documentation.

apache ant ivy conditionally build a module

I have a usecase where in I had to create a new module in out project. Our main project has multiple modules and each module is a java project. We are using ivy for dependency resolution. Now the probkem is that in the new module , I had to use java 1.7 API (WatchService) which is not there in java 1.6. Now in build.xml I can check for the java version and accordingly build this new module depending on the java -version. The problem comes in ivy.xml of or main web project where I have to mention the jar file of the new module as a dependency to include in the generated war file. If the java version is 1.7 , then in that case problem wont be there as the jar will be build and the its dependency will be resolved. the problem arises when the java version is 1.6. The jar file wont be created and when its time to generate the war file, ivy wont be able to resolve the dependency as the jar file is not there. Maybe the approach that I am trying to apply here is not fine. Please advice me on how to work around this particular use case.
rampal
In ivy you can use configurations to maintain different sets of depenedencies:
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<configurations>
<conf name="compile_jdk7" description="Java JDK7 compile dependencies"/>
<conf name="compile_jdk6" description="Java JDK6 compile dependencies"/>
</configurations>
<dependencies>
<!-- JDK7 dependencies -->
<dependency org="org.myorg" name="module1" rev="latest.integration" conf="compile_jdk7->default"/>
<dependency org="org.myorg" name="module2" rev="latest.integration" conf="compile_jdk7->default"/>
<dependency org="org.myorg" name="module3" rev="latest.integration" conf="compile_jdk7->default"/>
<!-- JDK6 dependencies -->
<dependency org="org.myorg" name="module1" rev="latest.integration" conf="compile_jdk6->default"/>
<dependency org="org.myorg" name="module3" rev="latest.integration" conf="compile_jdk6->default"/>
</dependencies>
</ivy-module>
and in the build file use a condition task to choose which configuration is used at run-time to populate the classpath, using the cachepath task:
<project name="demo" default="compile" xmlns:ivy="antlib:org.apache.ivy.ant">
<condition property="compile.config" value="compile_jdk7">
<equals arg1="${ant.java.version}" arg2="1.7"/>
</condition>
<condition property="compile.config" value="compile_jdk6">
<equals arg1="${ant.java.version}" arg2="1.6"/>
</condition>
<target name="resolve" description="Use ivy to resolve classpaths">
<ivy:cachepath pathid="compile.path" conf="${compile.config}"/>
</target>
<target name="compile" depends="resolve" description="Compile code">
<javac ...... classpathref="compile.path"/>
</target>
</project>

How do I exclude some dependencies without forcing other dependencies to define configurations

Our bootstrap process uses an ivy conf to deliver a build harness and some tools (ant libs). Our default configuration should deliver compilation and runtime dependencies.
I'd like conf="bootstrap" to only deliver the harness and I'd like the developers to be able to add deps without needing to wrestle with configurations.
I initially tried creating a default configuration but this required dependencies to do likewise which isn't what I want.
I tried default="default->*" but then my bootstrap gets included in default.
How can I keep these two separate without imposing demands on the dependencies or forcing conf="default->*" to be added to all of my "default" dependencies?
<configurations default="default">
<conf name="bootstrap" visibility="private" description="Scripts/Tools for Build Sys"/>
<conf name="default" description="Dependencies Used By This Module"/>
</configurations>
<dependencies>
<dependency conf="bootstrap->default" org="myorg" name="build-harness" rev="1.+"/>
<dependency org="myorg" name="logging" rev="1.0.0.+"/>
</dependencies>
If I define a configuration then do all of my deps need to do so as well? Is there a way to setup a default mapping?
Thanks for the help
Peter
I believe this is what I want:
set default configuration mapping to include any dep config in my default
add default and a private bootstrap configuration
add my build harness as 'bootstrap' and link it to the harnesses default - since the harness lacks user defined conf default = '*'
When I retrieve with no configuration I get the default which is all the compilation / runtime dependencies. When I retrieve 'bootstrap' conf I just get the bootstrap.
<configurations defaultconfmapping="default->*">
<conf name="bootstrap" visibility="private" description="Scripts/Tools for Build Sys"/>
<conf name="default" description="Dependencies Used By This Module"/>
</configurations>
<dependencies>
<dependency conf="bootstrap->default" org="myorg" name="build-harness" rev="1.+"/>
<dependency org="myorg" name="logging" rev="1.0.0.+"/>
</dependencies>

ivy simple shared repository

I am trying to compile all sub projects of one big project at my company into many jars with managed dependencies, so that not everybody who works at one project only needs to download the latest jars from a shared repository.
ivy seems to be the solution for our problem, because ivy says that it integrates with ant (out build system) very well. But I cant get through the tutorials, they are all somehow more confusing than helpful.
All I want to achieve for the beginning is to have two small Projects. The first one has one class with one method, the second one is just calling this method. The fist project should compile into a jar that is then downloaded by the second project from the shared repository.
Thanks for your help.
A multi-module project is described in the documentation:
http://ant.apache.org/ivy/history/latest-milestone/tutorial/multiproject.html
and the source code is available in subversion:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/example/multi-project/
The simplified summary of how it works:
Wrapper build
Invokes each individual module build in the correct order. If Module A depends on module B, then B will be built first:
<project xmlns:ivy="antlib:org.apache.ivy.ant" name="build-all" default="build">
<!--
==========================================================================
Use the ivy buildlist task to create an ordered list of sub-project builds
==========================================================================
-->
<target name="build-list">
<ivy:buildlist reference="build-path">
<fileset dir="." includes="modules/**/build.xml"/>
</ivy:buildlist>
</target>
<!--
==============================
Invoke targets in sub-projects
==============================
-->
<target name="build" depends="build-list" description="Invoke build target on sub-projects">
<subant target="build" buildpathref="build-path" />
</target>
</project>
For more information see the buildlist documentation.
Module build
Each module will download it's dependencies at the beginning of it's build
<target name="init">
<ivy:settings file="../../ivysettings.xml"/>
<ivy:resolve/>
</target>
At at the end, will publish it's built artifacts:
<target name="publish" depends="build" description="Publish module artifacts to the respository">
<ivy:publish resolver="${publish.resolver}" pubrevision="${publish.revision}" overwrite="true">
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>
Don't forget that for all this to work each module must declare what it depends on and what it publishes
<ivy-module version='2.0'>
<info organisation='com.myorg' module='mymod'/>
<publications>
<artifact name="mymod" type="jar"/>
</publications>
<dependencies>
..
</dependencies>
</ivy-module>

Split retrieved artifacts in two separate lib directories

In my web application, there are two separate lib directories:
/lib, and
/web/webroot/WEB-INF/lib.
The idea behind it is that libraries in the latter one are used by front-end code only, and the first one by both the front-end and the business logic code. There is a class loader in place which lets the business logic code not see the jars in /web/webroot/WEB-INF/lib.
How can I tell ivy that certain dependencies should go to the second directory while all others go to first one?
It's not trival since the the web class loader can see jars in both directories and I don't want jars to be in both directories.
Configurations are used to create logical groupings of dependencies:
ivy.xml
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<configurations>
<conf name="frontEnd" description="Jars used by front end"/>
<conf name="businessLogic" description="Jars used for business logic"/>
</configurations>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.5" conf="businessLogic->default"/>
<dependency org="commons-codec" name="commons-codec" rev="1.4" conf="businessLogic->default"/>
<dependency org="commons-cli" name="commons-cli" rev="1.2" conf="frontEnd->default"/>
<dependency org="commons-logging" name="commons-logging" rev="1.1.1" conf="frontEnd->default"/>
</dependencies>
</ivy-module>
The ivy retrieve ant task can use these configurations to populate your directories:
build.xml
<target name="init" description="--> retrieve dependencies with ivy">
<ivy:retrieve conf="businessLogic" pattern="lib/[artifact].[ext]"/>
<ivy:retrieve conf="frontEnd" pattern="web/webroot/WEB-INF/lib/[artifact].[ext]"/>
</target>
Example
$ find . -type f
./build.xml
./ivy.xml
./lib/commons-lang.jar
./lib/commons-codec.jar
./web/webroot/WEB-INF/lib/commons-cli.jar
./web/webroot/WEB-INF/lib/commons-logging.jar