Apache Ivy Resolution Concerns - apache

New to Apache Ivy and I'm configuring the latest-strategies element in my settings file, and am opting to go with the lexiconographic strategy for a number of reasons. But something just dawned on me, and has me worried about Ivy in general. I'm sure I'm just not seeing the "forest" through the "trees", but I absolutely need to gain clarity on this before I can proceed.
My project will use several other homegrown JARs as dependencies. Other developers may be actively working on these other JARs, and may introduce a bug at some point. If my project uses Ivy to always pull down the latest version of these other dependencies, then Ivy may inadvertently pull down a new bug when it goes to build.
What's the common solution here, or what do best practices dictate?
Is there a way to cherry pick which versions of which JARs my project uses? That way I'm not concerned with latest-strategies at all, or lexiconographic order, etc. That would seem to alleviate the problem, but may violate best practices.
Any input is appreciated, as always!

In such situation we used to use tags on trunk. When developer creates tag he must change a version number of a published ivy module. In this case when you want to use stable version of module you could resolve it by certain version (1.2.3) or by latest version from some range (1.2.+). The latest-development strategy pull out the latest unstable trunk or branch version of a module.

Related

Versioning APIs during internal development

In our team we have a number of APIs specified using the Open API Specification (formerly Swagger). We use Maven and OpenAPI Generator to generate code, build and publish the artifact to our local nexus. We build our code on TeamCity. The artifact is given the version that is specified in the pom.xml file of Maven.
During development we only use snapshot versions, that is versions which can be overwritten and will be cleaned up. This is opposite to release versions, that cannot be overwritten and needs administrative privileges to clean up. The reason for this is, that a developer usually changes a little bit at the time, which is much more convenient with snapshot versions. This also makes cleaning up outdated unreleased artifacts much easier.
Our problem is, that from time to time a developer makes API changes but forgets to set a new version. This works fine locally, but when the code is build on TeamCity the changed API overwrites the artifact of an older version. A developer not working on this branch will then experience a compile error, because the code does not match the API artifact being used.
What does others do? Is there a best practice? Preferably with standard tools. We have tried many things and nothing works well. At the same time this issue is so basic that someone must have a good solution - or at least experience enough to point to the least bad solution.

Trying to quickly resurrect an old Maven built project

First day on a project and first day with Maven and I've already wasted a lot of time trying to get it to build.
It appears the issue is that this old project has config, POMs, etc, that have many broken URLs embedded in them. i.e. Maven generated stack traces are presenting lots of URLs that are broken when trying to download project dependencies.
I have been given only the project source which includes Maven config files. I have not been supplied with existing Maven repositories, project dependent libraries or any build environment, etc.
I have been hacking away at these files but I don't get very far with each build attempt.
Am I doing something fundamentally wrong or is this Maven config really stuck in 2008?
Update:
My POM really was stuck in 2008, i.e. by virtue of versioning, it is a snapshot in time while the rest of the Java world moves on.
Some of the dependencies were no longer in any repositories, most of which were defunct projects and so I've ceased to use them. I had to rewrite the entire POM. I had to spend a lot of time tweaking versions to ensure compatibility between dependencies and between plugins. After much battling; some plugins just wouldn't coexist, clobbering each other.
All in all, it was many, many hours effort...too many for this project with only one developer, and I believe I only now know enough to be dangerous.
The good ol' IDE build system would have been a better choice in this instance.
ftr's advice (in the comments section) is right: Maven can't download certain dependencies, but that doesn't necessarily mean that those dependencies don't exist anymore. It could just be that the extra-repos section of the Maven configuration is now missing certain repositories, and/or there's some other connection issue (like bad proxy config - which may lead to you being able to access certain repos but not others).
I've been in a similar situation, and found out that while initially Maven reported errors when trying to download about 80% of the dependencies, after various tweaks on Maven's config I ended up making it download all of the dependencies (well except one which was really just a custom jar somebody did and which was fetched directly from the local file system, but that's besides the point).
Here's what I'd do:
Of all the dependencies that Maven says it can't download, try to spot 2 or 3 which are "well know" (like maybe if it says it can't download Servlet or some Spring library, write down the exact URL's he's trying to contact for those).
Manually check if those URL are indeed accessible (via browser). If so, make sure that the dependencies exist for the version Maven is looking for. Maybe they have been updated since the project was created, and the old version is no longer kept. In this case, 90% of the time the solution is to simply update Maven's pom to point to the new version.
If manually checking the dependency's URL shows you that in fact the dependency exists, for the version Maven is looking for, make sure there's no proxy or some other form of internet connection "extra config" which is done for your browser, but not for Maven. If that's the case, just update Maven's config with all those extra params (proxy, proxy authentication, etc).
If the dependency URL doesn't exist at all, try googling to see if that dependency doesn't now exist on some other repo. For example many of the JBoss dependencies (like Hibernate, etc) have changed repo location somewhere around 2007-2009. If that's the case just add the new repo to Maven's repo list (and remove the old one if it no longer exists).
Finally, the good old shameful way to fix this is to go to a colleague which has (or had) something to do with your project at some point, and copy his local Maven repo to your machine :)

maven2 dependencies

In a pom.xml, when specifying a dependency version, what is the difference between LATEST and [0,) ?
In my opinion they should be equivalent, but for some dependencies, LATEST does not match any version, whereas [0,) does.
In my opinion they should be equivalent, but for some dependencies, LATEST does not match any version, whereas [0,) does.
In theory, LATEST is the latest released or snapshot version (see Rich Seller's excellent answer on the special RELEASE and LATEST versions) so I would indeed expect the same behavior as with the [0,) range. Out of curiosity, can you provide an example where LATEST doesn't match?
That being said, I don't recommend using the LATEST nor RELEASE special versions as they make your build more fragile and harm the build reproducibility (you don't really want your build to suddenly start to fail because of some uncontrolled update). Admittedly, they're considered as a bad idea and references have been removed from the documentation (except from an untranslated part of the German version of the Definitive Guide)
and they are no longer supported in Maven 3.x.
You are thus strongly invited to not use them at all (bad practice, deprecated, not supported in the next version).
And I somehow consider the same applies to version ranges (in general), I don't recommend them either as I wrote many times in previous answers or comments. See for example:
Managing maven dependancies - New Versions and Non-Repo libraries
Maven automatic SNAPSHOT update
Debugging Maven’s “The artifact has no valid ranges”
Follow-up after comment
Here's an example (among many):
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>[0,)</version>
</dependency>
-> matches version 1.5.3 Whereas:
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>LATEST</version>
</dependency>
-> cannot be resolved
I'm not 100% but I don't think this artifact is providing the right maven-metadata.xml for this feature to work. I think metadata should include <release> and <latest> elements like for maven plugins (see for example this maven-metadata.xml). But I wouldn't spend too much time on this for the aforementioned reasons, just forget this LATEST stuff.
When you depend on a plugin or a
dependency, you can use the a version
value of LATEST or RELEASE. LATEST
refers to the latest released or
snapshot version of a particular
artifact, the most recently deployed
artifact in a particular repository.
RELEASE refers to the last
non-snapshot release in the
repository. In general, it is not a
best practice to design software which
depends on a non-specific version of
an artifact. If you are developing
software, you might want to use
RELEASE or LATEST as a convenience so
that you don't have to update version
numbers when a new release of a
third-party library is released. When
you release software, you should
always make sure that your project
depends on specific versions to reduce
the chances of your build or your
project being affected by a software
release not under your control. Use
LATEST and RELEASE with caution, if at
all.
See, for further information regarding this topic.
Make sure that the artifact you're looking for is present in your local repository.
However, I have to warn you about the LATEST and RELEASE version markers, as the documentation extract says, it is consider a bad practice to work with those. In fact, I think the LATEST and the RELEASE version markers will no longer be supported in Maven 3.X.
My recommendation is that you drop it usage completely and stick to the specific version notation.
EDIT:
Here is a POST that addressed this exact same information, but more thoughtfully.
Thanks to #Pascal Thivent for the observation :) I always include reference to the other StackOverflow questions that deal with the same subject I'm discussing.

Archivable, replicable releases when building with Maven: is there a right way?

We have a largish standalone (i.e. not Java EE) commercial Java project (10,000+ classes, four or five SVN repositories, ten or twenty third-party libraries) that's in the process of switching over to Maven. Unfortunately only one engineer (in a team of a dozen or so distributed across three countries) has any prior Maven experience, so we're kind of figuring it out as we go.
In the old Ant way of doing things, we'd:
check out source code from three or four repositories
compile it all into a single monolithic JAR
release that (as part of a ZIP file with library JARs, an installer, various config files, etc.)
check the JAR into SVN so we had a record of what the customers had actually got.
Now, we've got a Maven repository full of artifacts, and a build process that depends on Maven having access to that repository. So if we need to replicate what we actually shipped to a customer, we need to do a build against a Maven repository that has all the proper versions of everything. This is doable, I guess, if in (some version of) the (SVN-controlled) POM files we set all the dependencies to released versions?
But it gives our release engineer the creepy-crawlies, because there doesn't seem to be any way:
to make sure that somebody doesn't clobber the copy of foo-api-1.2.3.jar on the WebDAV server by mistake (the WebDAV server has access control, but that wouldn't stop a buggy build script)
to detect it if they did
to recover afterwards
His idea is, for release builds, to use a local file system as the repository rather than the WebDAV server, and put that local repository under SVN control.
Our one Maven-experienced engineer doesn't like that -- I guess because he doesn't like putting binaries under version control? -- and suggests that maybe the professional version of the Nexus server can solve the clobbering or clobber-tracking/recovery problem.
Personally, I'm not happy (sorry, Sonatype readers) with shelling out money for a non-free build system when we haven't even seen any benefit from the free version yet, and there's no guarantee it will actually solve the problem.
So our choices seem to be:
WebDAV server
Pros: only one server, also accessible by devs, ...?
Cons: easy clobbering, no clobber-tracking/recovery
Local file system
Pros: can be placed under revision control
Cons: only works with the distribution script
Frankly, both of these seem like hacks to me, and I have to wonder if there isn't a better way to do this.
So: Is there a right thing to do here?
I'm not sure to get everything but I would:
Use the maven-release-plugin (which automates the release process i.e. execute all the steps documented in release:prepare).
Use WebDAV with anonymous read-only and authenticated write policy (so only release engineer can actually deploy released artifacts to the corporate repo).
There is a no need to put generated artifacts under version control (if you have the poms under version control). I don't see the benefits of using the local file system instead of WebDAV (this is not providing more security, you can secure WebDAV as well). I don't see what the commercial version of Nexus would solve here.
Nexus has a setting which prevents you from clobbering an already released artefact in a release repository.
For a team of about a dozen, the free version of Nexus should be enough.

Should we store JRE in CVS/SVN?

I want to bundle JRE 6.0 together with my java application. All my source code reside in CVS. My client will check-out the code and build it themselves. Should I store JRE in CVS?
I normally advocate putting most everything in source control, but this seems a little excessive. Why ?
the JRE is readily available from http://java.sun.com
it doesn't change that often. I'd expect you to specify a minimum version for your code to run against (e.g. 1.5, 1.6 etc.)
I would not put a JDK or JRE into a source code repository:
It is bad practice to put externally versioned things into your version control because it usually leads to over-constraining, obscuring and/or hard-wiring your app's external dependencies. (Maven or Ivy are good solutions for dealing with external dependencies, though not in this case,)
Putting binaries into version control is a bad idea for some version control systems.
But I think your real problem (actually, your user's organization's problem) is the IT folks who refuse to contemplate upgrading the JRE:
They need to be made aware of the
fact that they can install multiple
JRE versions on the one machine, and
configure apps to launch with the JRE
version they require. (It is trivial
on Linux ...)
They need to be made aware of the fact
that their policy is an impediment to
progress.
They need to be made aware of the fact
that their policy is a potential security
issue. If they force users to deploy their
own copies of JDKs / JREs in random places,
it will be difficult to ensure that JRE security
patches get applied. (Besides, 1.4.2 is due
to be end-of-life'd soonish, and security
patches for it will cease.)
EDIT: and there is also the legal question of whether "redistributing" a JRE out of your source code repository is a violation of Sun's click-through JRE/JDK download license. (I don't know ...)
As best practice, you shouldn't keep any binary files in the source control system. For Java developers there is maven that does it's work better in versioning jar files. The reason is that we want to keep our source repository as small as possible so it is faster for those that checks out our code for the first time.
But if you still want to keep binary files in the source control, it would be best to avoid using CVS, because CVS is bad in versioning binary files. You can search with google, why it is bad. If you use SVN, then it still okay because SVN handles binary files much better than CVS.
I see nothing wrong with storing the JRE in CVS.
However, it's not so important whether you do or not as long as your script can pull it as part of the build. For example, if you want to host a downloadable jre.zip on an HTTP server, or point to it in a Maven repo, that's just as good.
Well won't your client all ready have the JRE if you expect him to compile the code before running it? The JDK contains the JRE.
Depends a lot on what you use to handle dependencies. If you use Maven, then create a maven package with the stuff you need, and host it on a local repository.
If you just have CVS (like we do) then it is fine to create big binary packages (since you will need them) which you can then put in CVS. Just be aware that they should be static for best CVS performance.
ALso note that the jsmooth package can create an EXE file of your jar with an JRE embedded in it. This might solve your deployment problem.
For remote compilation, Eclipse can work with a plain JRE. You just need to tell Eclipse where JRE you already have prepared above is located on the disk. There is also a folder inside the Eclipse distribution where the launcher looks automatically.
I'm wondering about the client building the application themselves. It will require some kind of Java compiler, most probably javac wich is part of the JDK. So your client will not only need a JRE, but a JDK as well (unless they will be using Jikes or another alternative compiler).
javac is capable of generating bytecode for previous versions of Java, so using a newer compiler should not pose any problems.
Personally, I would not include large binaries like a JRE as part of my own repository. The JRE can be considered very stable and just listing the minimum version required should be enough. Installing a JRE is also something quite different than installing a single Java application. The two activities should not be mixed.