Classpath issue using Ivy - java

I'm using Ivy to manage my dependencies, and It's causing me issues with easymock
my ivy.xml file has the following:
<dependency org="easymock" name="easymock" rev="2.5.+" conf="compile,test -> default" />
and then I follow with other library dependencies, hoping that in case some other library uses another version of easymock then at least my library gets the correct one.
but then after I resolve, in eclipse i can see that there are 2 versions of easymock (1.2 and 2.5) and then the 1.2 is listed first.
and when I run my unit test, I'm getting a java.lang.NoSuchMethodError on the contstructor of org.easymock.internal.RecordState which takes org.easymock.internal.IMocksBehavior.
which suggest I'm hitting the old version of EasyMock.
Any ideas how can I get around this issue?

Generate an ivy dependency report to see exactly what versions ivy is using, for each configuration:
<ivy:resolve/>
<ivy:report todir='${ivy.reports}' graph='false' xml='false'/>
Normally when ivy encounters two versions of the same library it will "evict" the older version.
To fix problems with incorrect conflict resolution I'd suggest reading the doco
Update
Ivy's conflict algorithms have always worked well for me in the past, but I must admit I never fully understood some of the complexities of transitive analysis. The following Maven article is worth reading:
http://guntherpopp.blogspot.com/2011/02/understanding-maven-dependency.html

The latest easymock I can see in the ibiblio mirrors is rev 2.0. That would mean, that 2.5 is not found and an older Version is used. Check your resolver settings and revisions.
It also helps to clean the cache once in a while (ivy:cleancache) so ivy is forced to search the repos for revisions.

Related

How to download dependencies inside a maven plugin?

What's the best way to download remote maven artifact from within a maven plugin while also supporting maven 2.2.x1), 3.0.x, 3.1.x and newer?
Aether seems a good candidate but it changed package namespace between 3.0.5 and 3.1 breaking compatibility.
There's pieces of information around,
some pointing towards maven-dependency-tree (as suggested in this SO post) (how?)
yet another to jcbi,
Another SO post which I think uses Aether underneath and presumably suffers from the same version incompatibility problem
Try to manually force your version of Ather based on the ResolveArtifact example
Try to port the really complex solution reflection solution from Apache Karaf
Some other util from maven-shared ?
So what's the correct, or at least working, way to go on about this?
1) Where Maven 2.2.x is a nice to have as pointed out by #khmarbaise is EoL
If you're in a plugin and want to have another plugin invoked, the best solution - by far - is to use Mojo Executor. This way, you won't rewrite the maven-dependency-plugin ...
Considering the maven version issues, well, I guess you should indeed give up on maven 2.* support.

What about new versions of third party libraries?

I'm maintaining an open source java library which has itself some dependencies to third party libraries (e.g. commons-beanutils:commons-beanutils-1.8.3). During development I just added the most recent version of such libraries to my pom. Now I did some changes to my library and realized that those versions are no more recent.
I'm now wondering which strategy is best practice with such dependencies.
My feeling says run mvn versions:use-latest-releases test.
I would recommend using mvn versions:display-dependency-updates and updating relevant libraries by hand.
It is not necessary to always use the latest version of the library.
Usually, should update your dependencies if:
you need a feature of the new version (for major and minor releases)
the update resolves a known bug (that affects you)
the update fixes a security problem.
resolves an incompatibility with another dependency
Otherwise, consider staying on your current version.
You might, temporarily consider using version ranges commons-beanutils:commons-beanutils:[1.8.0,1.9.0) to always use the latest bugfix version. Note however, that this results in non-reproducable builds and must be changed before releasing your project.

Preferring the latest jar in a sea of dependencies (java)

I have a large Ivy project, and Ive noticed that my code, which run well in eclipse, cause a compile error when run in ant. I've narrowed the problem down to the following line :
FileUtils.write(...).
This line fails - during compilation --- the method is simply not found. Obviously, my code is dependant on apache's commons-io library. And its quite clear that the current commons-io has this method.
http://commons.apache.org/io/apidocs/org/apache/commons/io/FileUtils.html
So what gives ?
I am pretty sure this is related to my ivy.xml -> the eclipse compiler is luckily (or smartly) using the newest possible version of commons-io , whereas my ivy.xml is using an older version which lacks this method.
Most important of all to not here is that ant is clearly using a different version of this jar.
So - my question is :
1) How can I tell ant / ivy to preferentially compile my code with the latest versions of libraries i specify ? I'm assuming that some of the dependencies in my lib/ may depend on older versions of commons-io .....
Also :
2) In this context, any hints about what to worry about regarding the how the classloader deals with duplicates in a multi-jar-dependent project would also be helpful to me ...
Dependency Reporting
I would suggest that you first add the generation of an ivy dependency report into your build, using the report task.
An example of this task is included in the following answer:
What is the Ivy equivalent of Maven's versions:display-dependency-updates?
This will tell you what versions of what jars are being used. Normally, ivy will use the version you specify in the ivy.xml file, however, another module might depend on a more recent version. Ivy's default behaviour is to always favour the most recent version of a Maven module.
Retrieve the latest dependency
If you want ivy to always prefer the latest version of a particular library then declare the dependency as follows:
<dependency org="commons-io" name="commons-io" rev="latest.release"/>
Ivy has a feature called Fixed and Dynamic Revisions.
You can set the version/revision of any artifact to latest-status like
rev="latest.integration" --> for development released
rev="latest.release" --> for released versions
Ivy takes the version with the highest version(you have specified) and omits all libraries with lower versions, so that you only have one lib in the ivy classpath (have a look at the resolution report, run ant -v (verbose mode))., which avoids having duplicate jars with conflicting versions.
This might be worth checking out, maybe you just have an old version defined in one of your ivy files.
As to the second point:
The classloader takes the class, that happens to be first in the classpath(or the jar that is first in the classpath). So mixed versions of the same lib, could behave differently on any system, depending on how the classpath is constructed.

Recompilation of dependencies with Maven - possible? Any performance boost?

I was thinking about dependencies in Maven. Maven downloads them but it is unknown for what target version of JVM are they compiled for and with what compiler. This raises two questions:
Would dependency recompilation bring faster dependency libraries?
I tried to search for this, but have not found sufficient answer. I found out that for 1.6 there is Split bytecode verification, that is done when compiling with target 1.6.
There is also a question Are Java 6's performance improvements in the JDK, JVM, or both? where it is mentioned that newer versions of javac might generate more optimized code.
Is it possible with Maven to perform recompilation of depending libraries? Would it be possible to configure Maven to download sources, put there information about 1.6 target and perform mvn clean install?
I am aware of Maven Dependency plugin and dependency:sources goal. That could be used for source download.
There is also Maven Replacer Plugin allowing replacing of text in files. As stated in its Issue 58 there was implemented XPath support for it.
Would it be possible to implement it with these plugins for dependency and also for its dependencies to perform it? I am not sure on how to perform it on the dependencies - perhaps with Maven Replacer Plugin injecting the configuration into unpacked dependencies pom.xml?
Or is there a simpler way to configure target java version with build profile in user's settings.xml that would take precedence of project settings and therefore avoiding pom.xml modification?
The javac does next to no optimisations and those it has have been there from the earliest days. (And could even be considered historical) If you have code built by Java 1.0 you might find an improvement but anything from the last tens years is likely to be as optimal in byte code as it is today.
Most of the optimisation is done in the JVM itself, and you should find that Java 6 update 30 runs faster than Java 6 update 0 even for the exactly the same code.
Let's think for a moment what a Maven dependency is. In the most general sense, it's a piece of software developed by someone else, living its own life cycle that:
is packed in an archive,
which exists in a repository
under a version descriptor (group, artifact, version).
That's all Maven guarantees. Note that it even does not say it's Java (could be resources, or native libraries, for example). Not much. Far too little to demand automatic recompilation of dependencies.

Managing maven dependancies - New Versions and Non-Repo libraries

Warning: I have just picked up Maven, so things mentioned might be wrong or not best practice.
I have a medium size open source project that I am migrating to Maven from the basic
NetBeans project management. This is not a developer team sharing the same room, this is 1-5 people over the internet sharing a SVN repo. Reading over the how-tos on dependencies, it seems that the only way to get dependencies is to get them from an online repo or install them locally.
This is not what I was looking for. I want to keep all dependencies in the SVN for many reasons including portability (anybody can pass by, check out the repo, build, and use; all that simply without manual adding to local repo's and whatnot), getting newer versions (discussed below), and manual versioning.
The other issue I have with the maven repository is that they are quite behind in versions. Logback for example is 0.9.18 in mvnbrowser but 0.9.24 officially. PircBot is 1.4.6 in mvnbrowser but 1.5.0 officially. Why such old versions?
Issue 3 is that I have dependencies that don't even exist in the repos, like Easier Java Persistence.
So
How can I force all dependencies to come from /lib for example
On a related note, can mvn build from library's SVN repo directly? Just curious
Is there an automatic way to get the newest version directly from a dependencies site/svn repo if they also use Maven? IE libraries like commons-lang or logback
Is there a better way of managing dependencies? (IE Ivy or some weird POM option I'm missing)
FYI, this is a Java project with 3 modules, project global dependencies and module specific dependencies.
Bonus points if it can work with the bundled version of Maven that comes with NetBeans.
Not a duplicate of
Maven: add a dependency to a jar by relative path - Not wanting to install to local repository
maven compile fails because i have a non-maven jar - Don't think a System dependency is the right answer
maven look for new versions of dependencies - Still uses(?) repository, just the latest (old) version
This is not what I was looking for. I want to keep all dependencies in the SVN for many reasons (...)
I will come back on this but the solution I described in Maven: add a dependency to a jar by relative path (using a file-based repository) allows to implement such a solution.
The other issue I have with the maven repository is that they are quite behind in versions. Logback for example is 0.9.18 in mvnbrowser but 0.9.24 officially. PircBot is 1.4.6 in mvnbrowser but 1.5.0 officially. Why such old versions?
It looks like mvnbrowser indices are totally out of date (making it useless as repository search engine) because the maven central repository does have logback-core-0.9.24.jar (the logback project is doing what has to be done to make this happen) but only has an old pircbot-1.4.2.jar. Why? Ask the pircbot team. Anyway, you're right, the central repository might not always have ultimate versions.
Issue 3 is that I have dependencies that don't even exist in the repos, like Easier Java Persistence.
Yeah, this happens too.
How can I force all dependencies to come from /lib for example
As previously hinted, you should re-read carefully the solution suggested in Maven: add a dependency to a jar by relative path. This solution is not about installing libraries to the local repository but is about using a file-based repository (that could thus be stored in SVN). You might have missed the point, this matches your use case. And also check Brett's answer for a variation.
On a related note, can mvn build from library's SVN repo directly? Just curious
Didn't get that one. Can you clarify?
Is there an automatic way to get the newest version directly from a dependencies site/svn repo if they also use Maven? IE libraries like commons-lang or logback
Maven supports version ranges and you could use a syntax allowing to use "any version greater than X". But I do NOT recommend using version ranges at all, for the sake of build reproducibility. You don't want the build to suddenly fail because of some automatic update that happened on your back. Only upgrade if you need bug fixes or new features, but do it explicitly (if it ain't broke, don't fix it).
You might also find mentions of the LATEST and RELEASE version markers. I don't recommend them neither for the same reasons as above and even less since they're removed from Maven 3.x.
Is there a better way of managing dependencies? (IE Ivy or some weird POM option I'm missing)
Can't say for Ivy. But in the Maven land, if you can't host up a "corporate" repository for your project (Nexus, Archiva, Artifactory), then the file-based repository is IMO the best approach.
Setup your own Maven repository.
http://archiva.apache.org/

Categories

Resources