Apache Ivy Config Standard - apache

I'm trying to set up my first Ivy-powered build and am running into implementation problems, and I feel like I don't fully understand Ivy terminologies & best practices, even though I've spent a great deal of time reading the official docs and countless articles.
I have a SVN server that I want to use as the central repository for all of my projects. I do not want to use any public repositories! When I need a JAR, I'll pull it down from one of those public repos, run a checksum for security, and then push it to my SVN server (wherebyit will be deemed to be a "certified" version of the JAR; by certified, I really mean "safe").
(1) I want all of my projects to share the same ivy-settings.xml file. Do I put this in my SVN root, or somewhere inside SVN that makes sense? Here was my tentative thinking:
svn://MyRepoRoot/
ivy/
ivy-settings.xml
artifacts/
Project1/
trunk/
ivy.xml
...
branches/
tags/
Project2/
...
...
The ivy/ directory would contain a master copy of my ivy-settings.xml file. It would also contain an artifacts subdirectory where all of my "certified" JARs/WARs would go (as well as any publications my projects produce for downstream modules). Can I request for commentary?
(2) Also, something that I'm just not getting, is if each of my projects (modules) have their own ivy.xml file, and I want that file to reference the "global ivy-settings.xml file, which should by all means fall under its own, non-module-related versioning scheme, how do I pull down, say, Project1's trunk as my working copy, but configure it with the settings file which is not even a part of the same SVN project?!?
Thanks to anyone who can help give me a little practical advice and better clarity!

The ivysettings.xml is not referenced in the ivy.xml. You need the ivysettings.xml in your ant tasks to find the defined resolver, which resolve the artifacts defined in the ivy.xml.
ivy.xml defines the dependencies and ivysettings.xml the (local) runtime environment for ivy. You can change the ivysettings.xml anytime without need to edit the ivy.xml files.
The ivysettings.xml needs to be referenced in yout (ant) build.xml in ivys <settings /> task.
As for the layout. I use the same approach and it works fine for me.
I wrote my antfiles, so that I need to have the ivy folder checked out parallel to my project(s).
Another approach could be svns externals. But I never tried that.
If your svn has access over http you could also use the url parameter of the task to access ivysettings.xml.

Related

Ivy Configuration Help

I've read the Ivy docs and a few other tutorials but am now trying to actually use it in a project for the first time and I am immediately presented with some roadblocks.
For the practice, I would like to write all my own config (XML) files. Not sure where to put ivy.xml, ivyconf.xml or ivy-settings.xml: do I put them in the same directory as my build.xml?
Besides ivy.xml, ivyconf.xml and ivy-settings.xml, are there any other config files that I should know about? Where do I place those?
Is the IvyDE just a graphical Eclipse plugin that graphically edits ivyconf.xml or does it edit other files?
Thanks for any input - it's been surprisingly difficult finding good info on this amazing tool!
You need only one file ivysettings.xml. You could place it beside build.xml or in any desired project directory. Optionally you could use one or more properties files for different uses.
Besides ivysettings.xml remeber about ivy cache directory. Often the best solution for all dependency resolution problems is to clean ivy cache by deleting this directory.
IvyDE allows you to resolve project dependencies inside Eclipse. IvyDE creates new classpath container named ivy.xml. Inside this container you'll find resolved libraries.
And I recomend you to use local or intranet ivy repository with Eclipse, because if resolving takes some time it will slow down loading of your projects.
For example I placed my ivysettings.xml that I use in my projects. As you can see for Eclipse there is eclipse-ivy.properties file. In this file I order Ivy to use local repository inside Eclipse. In Ant script I use remote repository by default, but there is an option to choose local repository.
<?xml version="1.0" encoding="UTF-8" ?>
<ivysettings>
<settings defaultResolver="${ivy.resolver}" />
<statuses default="development">
<status name="release" integration="false"/>
<status name="integration" integration="true"/>
<status name="development" integration="true"/>
</statuses>
<resolvers>
<ssh name="remote" checkconsistency="true" checkmodified="true" descriptor="required">
<ivy pattern="ssh://***/home/ivy/repository/[organisation]/[module]/[revision]/ivy.xml"/>
<artifact pattern="ssh://***/home/ivy/repository/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
</ssh>
<filesystem name="local">
<ivy pattern="${user.home}/.local-ivy-repository/[organisation]/[module]/[revision]/ivy.xml"/>
<artifact pattern="${user.home}/.local-ivy-repository/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
</ivysettings>
elipse-ivy.properties:
ivy.resolver=local
In general, it's best to create a single standardized ivy-settings.xml file and host it in a location where your builds can get to it easily. This file will usually be the same for all projects and rarely change once you've got it setup properly. In my development group, we host the ivy-settings.xml file on a web server so that it can easily be referenced by URL.
We build with Ant so we've also come up with a standardized ant build file which can either be hosted somewhere and imported into an Ant build script or simply copied to a project's directory if any kind of customization is necessary.
I've found that it's best to leave the Ivy configuration files as is and do any kind of customization by overriding the default values in your build scripts and/or ivy.xml files. Just about anything you'd need to change can be overridden. I recommend leaving the Ivy configuration files unchanged because it makes it much easier for other users to build your projects. If you've got a bunch of changes to your config files, any other developer wishing to build your project will have to replicate those changes on their local Ivy installs just to run a local build. That's bad mojo.
The IvyDE plugin provides editors for your ivy.xml and ivy-settings.xml files. According to the documentation, it also provides ways to automatically download your project's dependencies, includes a custom console and a reverse dependency explorer to help troubleshoot and resolve dependency conflicts. I only use the editors, though, so I can't vouch for the other tools.
Like Alexey, I'd recommend using a repository manager with Ivy. Artifactory does the job nicely; It's easy to setup and rock solid once it's running.
I agree that the documentation leaves much to be desired; it took me several weeks of experimentation to really grasp how all the pieces fit together. In the end, it was entirely worth it. Once you've got all the kinks ironed out, a well tuned artifact management system is truly something beautiful to behold.

Apache Ivy Best Practices

Hi I'm reading up on Ivy for the first time and had a few quick questions:
Need confirmation: the IvyDE plugin is used to configure just the ivyconf.xml file for all workspace projects, correct?
Where does this ivyconf.xml live? I'm running Windows 7 and can't find this hidden .ivy directory anywhere!
Where do you usually place a project's ivy.xml and other xml config files?
Thanks for any nudges in the right direction!
IvyDE allow you to resolve dependencies per project. You could use separate ivyconf.xml in different projects.
You could place ivyconf.xml (or ivysettings.xml) where you want. You could use one per project (as I do) or one for all projects (as I did before).
Usually I put ivy.xml beside Ant's build.xml in the root of my project. But ivysettings.xml I put in project/etc/ivysettings/ directory.
My team uses a separate build project in Eclipse that stores the ivysettings.xml file. The IvyDE plugin provides the Ivy dependency container that the Java projects can use. IvyDE can optionally allow inter-project dependency resolution, but this is off by default.
I'd suggest changing the order of classpath entries in the Ivy Classpath configuration to lexical, otherwise it shows dependencies in the order of the ivy.xml file.
Each project should have their own ivy.xml file - we also follow the same pattern as Alexey uses of using the project's top-level directory.
I've never used an ivyconf.xml file - a quick google suggests this is an alternative (older, deprecated?) name for the ivysettings.xml file.
You will need to write your own ivysettings.xml file to tell IvyDE where your repositories are and which resolvers to use. Leave a comment if you're interested in an example ivysettings.xml file.
Which repositories are you using? Maven Central? Setting up your own repository with Nexus, Artifactory or just using the file system?

Maven - installing artifacts to a local repository in workspace

I'd like to have a way in which 'mvn install' puts files in a repository folder under my source (checkout) root, while using 3rd party dependencies from ~/.m2/repository.
So after 'mvn install', the layout is:
/work/project/
repository
com/example/foo-1.0.jar
com/example/bar-1.0.jar
foo
src/main/java
bar
src/main/java
~/.m2/repository
log4j/log4j/1.2/log4j-1.2.jar
(In particular, /work/project/repository does not contain log4j)
In essense, I'm looking for a way of creating a composite repository that references other repositories
My intention is to be able to have multiple checkouts of the same source and work on each without overwriting each other in the local repository with 'install'. Multiple checkouts can be because of working on different branches in cvs/svn but in my case it is due to cloning of the master branch in git (in git, each clone is like a branch). I don't like the alternatives which are to use a special version/classifier per checkout or to reinstall (rebuild) everything each time I switch.
Maven can search multiple repositories (local, remote, "fake" remote) to resolve dependencies but there is only ONE local repository where artifacts get installed during install. It would be a real nightmare to install artifacts into specific locations and to maintain this list without breaking anything, that would just not work, you don't want to do this.
But, TBH, I don't get the point. So, why do you want to do this? There might be alternative and much simpler solutions, like installing your artifacts in the local repository and then copying them under your project root. Why wouldn't this work? I'd really like to know the final intention though.
UPDATE: Having read the update of the initial question, the only solution I can think of (given that you don't want to use different versions/tags) would be to use two local repositories and to switch between them (very error prone though).
To do so, either use different user accounts (as the local repository is user specific by default).
Or update your ~/.m2/settings.xml each time you want to switch:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>${user.home}/.m2/repository</localRepository>
<!--localRepository>${user.home}/.m2/repository2</localRepository-->
...
</settings>
Or have another settings.xml and point on it using the --settings option:
mvn install --settings /path/to/alternate/settings.xml
Or specify the alternate location on the command line using the -Dmaven.repo.local option:
mvn -Dmaven.repo.local=/path/to/repo
These solutions are all error prone as I said and none of them is very satisfying. Even if you might have very good reasons to work on several branches in parallel, your use case (not rebuilding everything) is not very common. Here, using distinct user accounts migh be the less worse solution IMO.
This is INDEED possible with the command line, and in fact is quite useful. For example, if you want to create an additional repo under your Eclipse project, you just do:
mvn install:install-file -DlocalRepositoryPath=repo \
-DcreateChecksum=true -Dpackaging=jar \
-Dfile=%2 -DgroupId=%3 -DartifactId=%4 -Dversion=%5
It's the "localRepositoryPath" parameter that will direct your install to any local repo you want.
I have this in a batch file that I run from my project root, and it installs the file into a "repo" directory within my project (hence the % parameters). So why would you want to do this? Well, let's you say you are professional services consultant, and you regularly go into customer locations where you are forced to use their security hardened laptops. You copy your self-contained project to their laptop from a USB stick, and presto, you can do your maven build no problem.
Generally, if you are using YOUR laptop, then it makes sense to have a single local repo that has everything in it. But to you who got cocky and said things like "why would you want to do that", I have some news...the world is a bigger place with more options than you might realize. If you are using laptops that are NOT yours, and you need to build your project on that laptop, get the resulting artifact, and then remove your project directory (and the local repo you just used), this is the way to go.
As to why you would want to have 2 local repos, the default .m2/repository is where the companies standard stuff goes, and the local "in project" repo is where YOUR stuff goes.
This is not possible with the command line client but you can create more complex repository layouts with a Maven repository server like Nexus.
The reason why it's not possible is that Maven allows to nest projects and most of them will reference each other, so installing each artifact in a different repository would lead to lots of searches on your local hard disk (or to failed builds when you start a build in a sub-project).
FYI: symlinks work in Windows7 and above so this kind of thing is easy to achieve if all your code goes in the same place in the local repo, i.e /com/myco/.
type mklink for details
I can see that you do not want to use special versions or classifiers but that is one of the best solutions to solve this problem. I work on the same project but different versions and each mvn install takes half an hour to build. The best option is to change the pom version appended with the change name, for example 1.0.0-SNAPSHOT-change1 that I'm working on thereby having multiple versions of the same project but with different code base.
It has made my life very easy in the long run. It helps run multiple builds at the same time without issues. Even during SCM push, we can skip the pom file from staging so there can always be 2 versions for you to work on.
In case you have a huge project with multiple sub-modules and want to change all the versions together, you can use the below command to do just that
mvn versions:set -DnewVersion=1.0.0-SNAPSHOT-change1 -DprocessAllModules
And once done, you can revert using
mvn versions:revert
I know this might be not what you are looking for, but it might help someone who wants to do this.

Maven: local development deploy vs bundling for distribution

Bear with me, I'm migrating from Ant to Maven2: I think I've hit one of those little things that was easy in Ant, but not so in Maven...
How do I handle the difference between a local deployment vs. creating an archive/bundle for distribution to another machine?
Let's assume my project's output is an EAR plus some additional config files. A developer that is actively working on the project will need to deploy and re-deploy frequently to his local app-server (say JBoss), while an Integration Engineer that is building for QA/production will need only to create the final archive assembly (tar/gz).
In Ant we had two targets for this: "dev-deploy" and "bundle". Both do a complete build, but differ in the final step: "dev-deploy" copies the EAR and config files to the respective local folders, while "bundle" just puts the EAR & config files in a tar.gz assembly.
How do you do this in Maven?
I've seen that the assembly plugin can create either archives (tar, gz, etc.) or exploded directories (from the same assembly descriptor). I can invoke either assembly:assembly or assembly:directory, but for the latter, how do I copy the final output to the local JBoss deployment folders? From a related post it seems that ad-hoc copying of files is not really what Maven is about, so an antrun copy is probably the most appropriate?
Finally, since the type of assembly may differ depending on who invokes it, it doesn't seem wise to bind assembly to the build lifecycle, not so? But this means that a developer will always need to invoke 'mvn package' followed by 'mvn assembly:directory' to rebuild and test a change. Conversely, an Integration Engineer will always need to run 'mvn package' followed by 'mvn assembly:assembly' to create the distributable archive. I was hoping for a one-command solution for each, or should I just script it?
In Ant we had two targets for this: "dev-deploy" and "bundle". Both do a complete build, but differ in the final step: "dev-deploy" copies the EAR and config files to the respective local folders, while "bundle" just puts the EAR & config files in a tar.gz assembly.
Not sure what you mean by respective local folders about "dev-deploy" but this sounds like what mvn pacakge is doing and "bundle" indeed sounds like a maven assembly.
I've seen that the assembly plugin can create either archives (tar, gz, etc.) or exploded directories (from the same assembly descriptor). I can invoke either assembly:assembly or assembly:directory, but for the latter, how do I copy the final output to the local JBoss deployment folders? From a related post it seems that ad-hoc copying of files is not really what Maven is about, so an antrun copy is probably the most appropriate?
I guess that we are talking about the Integration Engineer's tasks here. As you didn't explain what the "bundle" contains exactly, what the target application server is (my understanding is that you are using JBoss for QA/production too but, again, this is a guess), if this bundle has to be deployed automatically, it's hard to imagine all solutions and/or alternatives to antrun. But indeed, to copy/move/unzip/whatever the assembly, the maven antrun plugin is a candidate.
Finally, since the type of assembly may differ depending on who invokes it, it doesn't seem wise to bind assembly to the build lifecycle, not so? But this means that a developer will always need to invoke 'mvn package' followed by 'mvn assembly:directory' to rebuild and test a change. Conversely, an Integration Engineer will always need to run 'mvn package' followed by 'mvn assembly:assembly' to create the distributable archive. I was hoping for a one-command solution for each, or should I just script it?
My understanding was that the Integration Engineer was building the bundle. Why would a developer need the bundle? This is confusing... Anyway, I don't really need the details to think of an answer. You could actually declare the maven assembly plugin into specific build profiles, one for development and one for integration, and bind either the single or the directory-single mojos to the project's build lifecycle in each profile. This would allow to use only one command and avoid any scripting (really, don't go this way).

Maven repository configurations

I've asked a similar question in which part of this was addressed, but I'd like to expand in more detail.
When configuring maven to look at internal repositories, is it best to put that information in the project pom or in a user's settings.xml? An explanation on why would be really helpful here.
thanks,
Jeff
You should always try to make the maven project so that it compiles from a clean checkout from source control in your local environment; without a settings.xml. In my opinion this means that you place any overrides to sensible default values in the user's settings.xml file. But the pom should contain sensible values that will work for everyone.
I encourage you to put the repository definition in the POM, this way any developer just grab a copy of the code and run Maven to get it compiled, without having to change things in his settings file.
I find the setting.xml file useful just for hacking Maven's behaviour in special situations, for example when one repository is not accessible due to a firewall and you need to use a mirror. But that's my personal opinion. Maven documentation gives you more freedom:
The settings element in the
settings.xml file contains elements
used to define values which configure
Maven execution in various ways, like
the pom.xml, but should not be bundled
to any specific project, or
distributed to an audience. These
include values such as the local
repository location, alternate remote
repository servers, and authentication
information.
If you have a local repository which is used in every single project you may add that at the settings.xml, just be sure that configuration is well documented, in my current project it's not and new developers struggle at the beginning when they try to compile something.
We use the user's settings.xml and include info in the README about what possible other repos may be needed.
In theory a given group-artifact-version is the same no matter which repo it comes from. It works pretty well for us. If you find yourself with two different assets that have the same group-artifact-version identifier, then that indicates you're doing something really bad.