What about new versions of third party libraries? - java

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.

Related

Removing a Version from a Maven Remote Repo

I have currently been working on my first Maven project and have run into some confusion with Maven versioning. I understand that while developing a new version the SNAPSHOT keyword should be used in the version number. I also understand that a non SNAPSHOT version should only be released once.
I was wondering if it were possible to delete an old version from a Maven remote repository. For example, if I don't version want 1.0.2 downloadable anymore, what should I do?
Additionally, Let's say I am working on version 1.0-SNAPSHOT. When I deploy version 1.0, will the last 1.0-SNAPSHOT version be deleted/replaced by its non SNAPSHOT counterpart?
Simple answer to this: A release version (without SNAPSHOT) is immutable. This includes it will be kept forever.
The reason is:
If someone uses your version 1.0.2 and you simply can delete it those > builds will fail without an obvious reason.
One word about the thing you mentioned:
I also understand that a non SNAPSHOT version should only be released once.
You can not release the same version twice. Never possible and should never. This would mean you would override and existing version which changes behaviour. This could also break other builds.
You can take a look at for example https://search.maven.org/artifact/javax.mail/mail you will find artifacts which are more than fifteen years old. They will never deleted cause It could be the case that someone is using them.
If you have an issue in your version 1.0.2 just simply create a new version 1.0.3 which fixes the issues. The version number should follow semantical versioning.
If you are running a version 1.0-SNAPSHOT during development and making a release of it (usually via maven-release-plugin) during the release of 1.0 usually the 1.0-SNAPSHOT versions will be automatically deleted. So the 1.0-SNAPSHOT is no longer available. This is the default configuration for maven repository managers.
If you use AWS S3 bucket as maven repository there is a brutal workaround. I've tested it and it works.
You can simply delete release folder eg 1.0.0/ on remote repository. Fact, it leaves some legacy version tag in main maven-metadata.xml but it will be overwritten when you perform next release of this version.

Maven pull an old version of a transitive dependency

I've written a library I've written that depends upon Guava version 20.0 (the last version that is compatible with JDK 1.7)
I've then written an application that uses that library and also uk.org.lidalia:slf4j-test:1.2.0 (with test scope). slf4j-test has a dependency on version 14.0.1 of Guava.
My problem is that my application is seeing two different versions of Guava as transitive dependencies and picks the OLDER version. Now when I call certain methods in my Library I get Class or Method not found exceptions.
I can (and have) excluded Guava as a dependency of slf4j-test, which fixes the problem for now, but the problem will return if I introduce another dependency which uses Guava.
So my question is: Why would Maven pick the older version of a dependency and how do I always make it pick the latest versions.
You cannot force Maven to always pick the latest version. But there are several things you can do:
If you declare the dependency in your own pom, this version always wins. So if you have a dependency on guava 20.0 in your pom, you will get exactly this.
If this is not suitable, you can put an entry into dependencyManagement which sets the version for guava. This will overwrite all transitively set versions (like the 14.0.1 in your example).
The Maven enforcer plugin has a rule that makes sure that all dependencies are evaluated to the latest version - but it does not pick that latest version, it only fails the build if it was not chosen. Then you need to choose it yourself by applying method (1) or (2) above.

Versions Maven Plugin: package not found after versions:use-latest-versions

When I execute in my Maven project the Versions Maven Plugin plugin with the command:
mvn versions:use-latest-versions
The pom.xml is updated with updated dependencies as it is supposed to do.
The problem is that some libraries are updated to version as new as the do not contains some of the packages used in previous versions so the compiler says package not found. Does anybody know how to avoid automatically? I mean, update to the latest version which have the packages and classes I am using in my code.
In my opinion, there is no easy way to determine which version update is "save".
Even if you would check that all classes you compile against still exist, method signatures might have changed. And even if all the method signatures stay the same, the behaviour might have changed, leading to runtime exception etc.
The only reasonable way I know to check a version update is to run a compile and run all test cases. Doing this for all combinations of possible version updates is possible but it will take a lot of time.
The plugin is not going to analyse your code and adjust the dependencies version accordingly.
The objective of the goal use-latest-versions is to upgrade your project to the latest release of your project dependencies, and as a result of you may have compilation and deployment problems.
Once you identified the problems you need to fix all the problems so that your whole project is upgraded to the latest releases of your dependencies.
The problem is that some libraries are updated to version as new as
the do not contains some of the packages used in previous versions so
the compiler says package not found. Does anybody know how to avoid
automatically? I mean, update to the latest version which have the
packages and classes I am using in my code.
Of course, it is not possible.
Updating dependencies is not a game of chance.
If you need to have the last version of a dependency, you should not worry about if this version breaks or doesn't break your code because you need it.
You update a library because you need to update that version. If you don't need to update your dependencies, don't update your dependencies, but if you need to do that, you should make the work to update your code too if necessary.

Gradle: Burning actual dependencies versions in release branch

In my team we develop several applications, all use the same in-house framework. This framework is separated to many sub modules, each with its own version, and each is published as a jar to artifactory (maven repository).
When we release an application we create a branch for it and we want to compile that branch against the latest release of each framework module (that's ok because in our nightly regressions we compile against the latest snapshot). We use gradle so this is done by setting the dependency version as "latest.release". This works great until we need to fix a bugs in production - then we release a patch for the released application by checking out the release branch, fixing the bug, compiling, validating and packaging the app.
Problem: latest.release now points to a different release version than the one we originally compiled against.
What I want: when releasing the app, burn all its resolved versions (the resolved latest.release) on the build.gradle (or in some other file) so when I compile it again in the future I will compile against the old releases.
I assume many developers face this issue, yet I haven't found any solution for this online. I never used maven but while searching for a solution I discovered there's a plugin in maven, release plugin, that does exactly what I need.
Would like to know if you have a solution for this problem.
Netflix has a plugin that handles locking dependency versions at releast time: https://github.com/nebula-plugins/gradle-dependency-lock-plugin
Alternatively, you can use this plugin: https://github.com/ben-manes/gradle-versions-plugin to identify dependencies that have newer versions, and replace them manually as needed.

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.

Categories

Resources