Command to get paths to jars for ivy-managed dependencies - ivy

Is there a way to get the paths to the JAR files for ivy-managed dependencies so that a program can be called from the command line and the JAR files are all correctly included in the class path.
Some thing like (for Linux bash and similar scripts):
java -cp `ivyget.sh ivy.xml`
which could then expand to
java -cp "/path/to/first.jar:/path/to/second.jar"
Is something like this possible?

Ivy can be used in a standalone fashion, see the documentation. I have included an example below.
While this is a nifty feature I prefer to just use ivy for downloading. If your java program has options (eg -option1 or --option2) then ivy is not capable of properly parsing the command-line.
Example
The following project is used to manage a database schema using liquibase
├── changesets
│   └── scottTiger.xml
├── ivy.xml
├── liquibase.properties
└── liquibase.sh
The project is executed by running the shell script
./liquibase.sh update
liquibase.sh
#!/bin/bash
java -jar $HOME/.ant/lib/ivy.jar \
-error \
-ivy ivy.xml \
-main liquibase.integration.commandline.Main \
-args $#
ivy.xml
The ivy file pulls in the liquibase and H2 database projects as dependencies
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<dependencies>
<dependency org="org.liquibase" name="liquibase-core" rev="latest.release" conf="default"/>
<dependency org="com.h2database" name="h2" rev="latest.release" conf="default"/>
</dependencies>
</ivy-module>
liquibase.properties
Run-time configuration file, where the DB type is set to H2.
url=jdbc:h2:./db/scottTiger
driver=org.h2.Driver
username=user
password=pass
changeLogFile=changesets/scottTiger.xml
logLevel=info

Related

getting error in ivy.xml throwing exception

I am getting the below exception upon ivy-configure tag , i have configured the ivy configure tag in my build-ivy.xml as shown below
my ivy.xml is at the below path..
/ops/ivy/ivy.xml
my ivy-settings.xml is at..
/ops/ivy/ivysettings.xml
and my ivy:configure entry in build.xml as shown below ...
<!-- Ivy -->
<target name="prepare" description="Ivy setting load">
<echo message="Saral in Prepare"/>
<delete dir="${project_dependencies}"/>
<mkdir dir="${project_dependencies}"/>
<path id="classpath">
<fileset dir="lib">
<include name="${ops.dir}/ivy/ivy-2.3.0.jar"/>
</fileset>
</path>
<ivy:configure file="${ops.dir}/ivy/ivysettings.xml" />
<ivy:retrieve type="jar" pattern="${project_dependencies}/[artifact].[ext]"/>
</target>
the error that i am getting is ...please advise where i need to configure ivy.xml
prepare:
[echo] Saral in Prepare
[delete] Deleting directory C:\DTSTOTALUPLOADED\Glacier\project_dependencies
[mkdir] Created dir: C:\DTSTOTALUPLOADED\Glacier\project_dependencies
[ivy:configure] :: Apache Ivy 2.3.0 - 20130110142753 :: http://ant.apache.org/ivy/ ::
[ivy:configure] :: loading settings :: file = C:\DTSTOTALUPLOADED\Glacier\ops\ivy\ivysettings.xml
[ivy:retrieve] C:\DTSTOTALUPLOADED\Glacier\ivy\ivy.xml (The system cannot find the path specified) in file:/C:/DTSTOTALUPLOADED/Glacier/ivy/ivy.xml
BUILD FAILED
folks please advise on this..!
Ivy is designed to manage a software projects dependencies, using an ivy file that is normally committed locally into the source code.
For a working example see:
How to avoid copying dependencies with Ivy
Additional info
Location of ivy file
Typically the project files look something like the following:
├── build.xml
├── ivy.xml <-- Ivy file detailing project dependencies
└── src
└── main
└── java
└── myorg
└── MyClass.java
Cleanup targets
I would suggest moving build cleanup logic into a separate set of targets and additionally leverage the cleancache ivy task.
<target name="clean" description="Cleans up files created by build">
<delete dir="build"/>
<delete dir="lib"/>
</target>
<target name="clean-all" depends="clean" description="Additionally purge ivy cache">
<ivy:cleancache/>
</target>
Managing classpath
A more efficient way to manage the build classpath is to use the ivy cachepath task instead of retrieve.
This approach is especially powerful if you use ivy configurations, allowing you to control multiple classpaths.
Bootstrapping ivy
I don't think the following code is redundant:
<path id="classpath">
<fileset dir="lib">
<include name="${ops.dir}/ivy/ivy-2.3.0.jar"/>
</fileset>
</path>
Adding the ivy jar onto a project path after ANT is started would be too late. Check your $ANT_HOME/lib or ~/.ant/lib directories. I'll bet the ivy jar is there already?

Ivy dependency management for legacy repository

We have a repository which doesn't have ivy.xml and other metadata files. Since, its published by another team which doesn't use ivy/maven but will continue to deliver code frequently.
The jars needed for dependency are stored in flat structure inside a single directory with no revision data. The organization / module /revision structure is absent.
Does ivy allow such dependency resolutions in the core product or will I have to write a custom resolver?
Thanks
The standard resolvers should be able to pick up the atifacts (url, filesystem, etc). The problem you'll face is that, by default, ivy assumes a revision never changes. Without version information you're going to have tweak the standard resolver settings to force ivy to always check the artifact.
The ivy concepts page explains how this works:
Some people, especially those coming from maven 2 land, like to use one special revision to handle often updated modules. In maven 2 this is called a SNAPSHOT version, and some argue that it helps save disk space to keep only one version for the high number of intermediary builds you can make whilst developing.
Ivy supports this kind of approach with the notion of "changing revision". A changing revision is just that: a revision for which Ivy should consider that the artifacts may change over time. To handle this, you can either specify a dependency as changing on the dependency tag, or use the changingPattern and changingMatcher attributes on your resolvers to indicate which revision or group of revisions should be considered as changing.
Personally I dislike this kind of dependency management. Your build is a moving goal post and it's hard to keep it stable.
I would encourage to to persuade the other team to at least append a build number to each artifact they publish. Your ivy build could then use a dynamic revision to resolve the artifact. The key point is that when you ship your code, your module will have a dependency against a specific version of its 3rd party libraries.
Update
The following is an example project. It uses Maven Central and a local repo, to download its dependencies.
├── build
│   ├── compile
│   │   ├── artifact1.jar <-- Changing artifact
│   │   └── slf4j-api.jar
│   ├── runtime
│   │   ├── artifact1.jar <-- Changing artifact
│   │   ├── artifact2.jar <-- Changing artifact
│   │   ├── log4j.jar
│   │   ├── slf4j-api.jar
│   │   └── slf4j-log4j12.jar
│   └── test
│   ├── artifact1.jar <-- Changing artifact
│   ├── artifact2.jar <-- Changing artifact
│   ├── artifact3.jar <-- Changing artifact
│   ├── hamcrest-core.jar
│   ├── junit.jar
│   ├── log4j.jar
│   ├── slf4j-api.jar
│   └── slf4j-log4j12.jar
├── build.xml
├── ivysettings.xml
└── ivy.xml
The local repo is un-versioned and has no ivy files. Normally the ivy resolvers require ivy files (or POM in the case of Maven) to determine if a remote module has changed. In the absence of metadata you can mark the dependency as changing in the ivy file.
build.xml
<project name="demo" default="build" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="build" description="do something">
<ivy:retrieve pattern="build/[conf]/[artifact].[ext]"/>
</target>
<target name="clean" description="Cleanup build files">
<delete dir="build"/>
</target>
<target name="clean-all" depends="clean" description="Additionally purge ivy cache">
<ivy:cleancache/>
</target>
</project>
Notes:
Stand build file using ivy. The retrieve task assembles the files into their various configuration groupings.
ivy.xml
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<configurations>
<conf name="compile" description="Required to compile application"/>
<conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
<conf name="test" description="Required for test only" extends="runtime"/>
</configurations>
<dependencies>
<!-- compile dependencies -->
<dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->default"/>
<dependency org="myorg" name="artifact1" rev="NA" conf="compile->default" changing="true"/>
<!-- runtime dependencies -->
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.5" conf="runtime->default"/>
<dependency org="myorg" name="artifact2" rev="NA" conf="runtime->default" changing="true"/>
<!-- test dependencies -->
<dependency org="junit" name="junit" rev="4.11" conf="test->default"/>
<dependency org="myorg" name="artifact3" rev="NA" conf="test->default" changing="true"/>
</dependencies>
</ivy-module>
Notes:
The "myorg" dependencies have a dummy "NA" entry as their revision and are marked as "changing".
ivysettings.xml
<ivysettings>
<settings defaultResolver="central" />
<resolvers>
<ibiblio name="central" m2compatible="true"/>
<url name="myorg-repo">
<artifact pattern="http://localhost:8080/userContent/[artifact].[ext]"/>
</url>
</resolvers>
<modules>
<module organisation="myorg" resolver="myorg-repo"/>
</modules>
</ivysettings>
Notes:
The "myorg-repo" resolver is setup to download only the "myorg" dependencies. This enables all other dependencies to be resolved by Maven Central.
The "myorg-repo" resolver just declares an artifact pattern, I'm assuming there are no ivy files to be retrieved.
Understanding ivy pattern helped me resolve the issue. The catch is never specify an ivy pattern whenever the repository doesn't have ivy files.

gradle - how to declare a dependency of a jar in a jar

Using gradle, I am consuming a build from an archiva repository. One of the jars (javax.jms_1.1.0.200810061358.jar) has the following content:
about.html
about_files
LICENSE.txt
jms.jar
META-INF
MANIFEST.MF
The jar I need is actually the jms.jar inside this javax.jms_1.1.0.200810061358.jar
The only way I've been able to consume this jar is by pulling jms.jar
out of the repository's javax.jms_1.1.0.200810081358.jar and saving it
to the file system and consuming it via:
repositories { flatDir: my_dir_with_jms.jar_in_it}
someone on the gradle list suggested using an Ivy packager resolver.
I looked at this link and was
left very confused. I do have other ivy resolvers set up like this:
addIvyPattern 'http://archivaserver:8080/archiva/repository/osgi-internal/[organisation]/[module]/[revision]/ivy_[revision].xml'
addArtifactPattern
"http://archivaserver:8080/archiva/repository/osgi-official/[organisation]/[organisation]/[module]_[revision](-[classifier]).[ext]"
Anyone know of a good solution to this?
Resolving a dependency inside a dependency would require the use of the ivy packager resolver.
I've never configured the package resolver from within Gradle, but I think it would work something like the following (Referencing webpage)
repositories {
add(new org.apache.ivy.plugins.resolver.packager.PackagerResolver()) {
name = 'local Ivy packagers'
buildRoot = file("${gradle.gradleUserHomeDir}/packager/build")
resourceCache = file("${gradle.gradleUserHomeDir}/packager/cache")
addIvyPattern "file:///${project.rootDir}/ivy/[organisation]/[module]/[revision]/ivy.xml"
addArtifactPattern "file:///${project.rootDir}/ivy/[organisation]/[module]/[revision]/packager.xml"
}
}
dependencies {
compile group: 'org.myorg', name: 'jms', version: '1.1.0.200810061358'
}
The resolver requires the following files for the declared dependency:
ivy/org.myorg/jms/1.1.0.200810061358/ivy.xml
ivy/org.myorg/jms/1.1.0.200810061358/packager.xml
ivy.xml
Describes the module and in this case declares what artifacts are published:
<ivy-module version="2.0">
<info organisation="org.myorg" module="jms" revision="1.1.0.200810061358" status="release"/>
<publications>
<artifact name="jms" type="jar"/>
</publications>
</ivy-module>
packager.xml
Describes where the enclosing archive is located and instructions on how to extract jms.jar:
<packager-module version="1.0">
<resource dest="archive" url="http://archivaserver:8080/archiva/repository/??/javax.jms_1.1.0.200810061358.jar" sha1="????"/>
<build>
<move file="archive/jms.jar" tofile="artifacts/jars/jms.jar"/>
</build>
</packager-module>
The content under the build tag is used to generate an ANT script. For more details read the "Packaging instructions" section of the ivy documentation

Maven: use dependencies from repository when running command line app?

I've used Maven to build my command line application. Now I'm going to distribute it as a jar file, and I need to handle the app's dependencies.
I don't want to include all dependencies in the jar file as described here.
The environment where my app will be run has Maven. I'd like Maven to run my jar looking at file META-INF/groupId/artifactId/pom.xml inside the package so it knows what the dependencies are and can find them in the repository.
Any ideas ?
Include a main class in the jar that 1) extracts the pom to a temporary file, and 2) launches a new maven process using this file with the -f parameter and the goals dependency:resolve and dependency:build-classpath
like this:
mvn -f /temp/tempfile.xml dependency:resolve dependency:build-classpath -DoutputFile=/temp/classpath.txt
then 3) reads the newly created classpath file and 4) launches a new java process using the new classpath file
java -cp yourjar.jar;<created classpath>
Your pom.xml will have to include all required repository information, of course
We can use, maven-jar-plugin instead, why because the classpath generated is not getting accommodated while copy paste with java command in command-line.
mvn -f /temp/tempfile.xml dependency:resolve dependency:build-classpath -DmdepoutputFile=/temp/classpath.txt
So wasn't able to succeed copying classpath.txt for the command,
java -cp yourjar.jar;<created classpath>
Mine is spring-boot application hence I have the following line with BOOT-INF/lib. For you it can be WEB-INF/lib in case of .war file or just lib/ in case of ant build based projects.
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>BOOT-INF/lib/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}</customClasspathLayout>
BOOT-INF, comes up by spring-boot:repackage maven command and with the use of plugin,-spring-boot-maven-plugin that I have not Included here.
Please find maven-jar-plugin config here.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.pakage.SampleApplication</mainClass>
<!--<classpathPrefix>lib/</classpathPrefix>-->
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>BOOT-INF/lib/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}</customClasspathLayout>
<!--<customClasspathLayout>BOOT-INF/lib/$${artifact.groupIdPath}/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}</customClasspathLayout>-->
</manifest>
</archive>
</configuration>
</plugin>

Include Maven dependencies in the assembly war?

I am creating an assembly with packaging=war.
I need to include few of the jars, which have been declared as project dependencies in pom.xml in my war (web-inf/lib)
How can I do this?
Edited on 15/10-
My project creates few assemblies, one of which is supposed to give packaging of type-war.
Some jar files, which are dependencies for the project(and have been declared in pom.xml)need be included in war under WEB-INF.
How can I include them or how can i point out their paths to my local nexus repository path?
Can you be more precise? By default, when you run the mvn clean install command on a war project, Maven 2 will include all dependencies in WEB-INF/lib directories, excluding the ones with the scope test and provided.
If you create your war file using an assembly, then you have an assembly.xml file, which defines the content of your final war file. In this file, you can specify the list of dependencies you want to include:
<assembly>
...
<dependencySets>
<dependencySet>
<includes>
<include>log4j:log4j</include>
<include>commons-lang:commons-lang</include>
...
</includes>
<unpack>false</unpack>
<outputDirectory>WEB-INF/lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
(in this example, I asked to add log4j and commons-lang dependencies).
For each dependency, you need to specify the groupId and the artifactId. The version is automatically detected regarding the list of dependencies you have set in your pom.xml file.