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.
Related
I'm trying to run Simple Hierarchy example of OWL API. I included owlapi-osgidistribution-4.0.2.jar and all libraries from its lib folder to the project class path. However I still have one unresolved import:
import static org.semanticweb.owlapi.search.EntitySearcher.getAnnotationObjects;
And one undefined method associated with that import:
for (OWLAnnotation anno : getAnnotationObjects(clazz, ontology)) {
anno.accept(le);
}
I see that EntitySearcher class is in the OWL API library. Have I missed something?
EntitySearcher is in the owlapi-api module, so should be found in your classpath.
That example is compiled routinely with each owlapi build, so it should not present any particular problem.
Note: I can't recall if the method you mention was added before or after 4.0.2 was released. It is possible that it was added for 4.1.0.
I went through the exact same instance of the problem yesterday, interesting coincidence.
The code that you're looking at is supposed to work with the latest version of the OWL API, namely 4.1.0-RC4. I've found hints to the problem browsing through the mailing list. Unfortunately the only available packaged version right now is the 4.0.2, and the latest version on the Maven repositories is 4.1.0-RC2, which didn't ship with the method used in the example.
The way I temporarily "solved" the problem was to use the Maven dependencies targeting version 4.1.0-RC2 and adding to the classpath the binary distribution for 4.1.0-RC4 built from the git repository (overriding the one for the older version resolved by Maven).
Assuming you know how to use Maven, this is the relevant entry of the POM file:
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>owlapi-osgidistribution</artifactId>
<version>4.1.0-RC2</version>
</dependency>
To build the latest version of OWL API, just clone the git repository or download it as a zip file, extract and then run mvn clean install: the jar you want to add to your classpath should be present in the ./distribution/target/ directory.
You're also likely to get some warnings about the logger, if you want to fix that as well you need to get the tarball of slf4j with version matching the one that was resolved by Maven (from here, the version I used is 1.7.7), build it and then add slf4j-simple-#.#.#.jar to your classpath.
Hope this helps.
I have a project which depends on a JAR file. The version of this JAR changes often and we are having a hard time trying to ensure we are using the correct one. It is also causing problems when investigating bugs: which version of JAR contains the bug. Some programmers may forget to update corresponding dependencies and include 2 versions of this JAR inside the project, so that an old version may be found by the classloader.
A question is how to account for this issue.
I have a following plan:
1) When an error occurs log the JAR name I am working with to ensure it is a correct version. I plan to use something like
this.getClass().getResource(someResourceINeedFromThatJar).getFile()
2) I can write a test to account for this. But I don't know how I can run a test AFTER the package phase of my Maven build
3) Maybe you can suggest something else for this?
Well, We have same scenario and solved issue by using maven dependencyManagement
It does two things.
Set a default version for dependencies in submodules/child projects
override the version of transitive dependencies
it does override a specified value in a transitive dependency.
The enforcer plugin does not ignore the dependencyManagement. But is unable to recognize the discrepancy since the transitive dependency's version was altered before it went to work.
Here is a nice article : You can go through it:
http://andydennie.com/2012/08/02/maven-enforcer-plugin-vs-dependencymanagement/
And another source: http://maven.apache.org/enforcer/maven-enforcer-plugin/
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.
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.
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/