Maven 2.0.9 was released today. I previously blogged about the changes to the process that will hopefully lead to more stable releases in the future. Today I want to talk about some important changes in the release itself that improve the user experience a bit.
Probably the biggest and most anticipated change is the shift towards specifying default versions for the core set of plugins. Before I go further, lets have a background lesson on how Maven handles the plugins and why this was a pain point for some users.
Unlike dependencies, Maven does not require a version of plugins to be specified. Ostensibly, this is because many plugins are introduced to the build lifecycle via one of the supported packaging types (jar,war,ear,etc). It’s not immediately obvious to a user exactly which plugins will be used and which versions they want to use. Requiring a version declaration in the pom for all plugins would immediately fail even the simplest of poms and is definately not newbie friendly.
If Maven encounters a plugin with no version declaration, regardless if introduced by the user or the packaging type, it will query the repository metadata to find the LATEST version. LATEST and RELEASE are keywords that have special meaning but are recorded in the maven.metadata.xml. The maven-dependency-plugin’s metdata is shown below:
<metadata> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.0-alpha-1-SNAPSHOT</version> <versioning> <latest>2.1-SNAPSHOT</latest> <release>2.0</release> <versions> <version>2.0-alpha-1-SNAPSHOT</version> <version>2.0-alpha-2-SNAPSHOT</version> <version>2.0-alpha-3-SNAPSHOT</version> <version>2.0-alpha-4-SNAPSHOT</version> <version>2.0-alpha-5-SNAPSHOT</version> <version>2.0-SNAPSHOT</version> <version>2.0-alpha-1</version> <version>2.0-alpha-2</version> <version>2.0-alpha-3</version> <version>2.0-alpha-4</version> <version>2.0</version> <version>2.1-SNAPSHOT</version> </versions> <lastUpdated>20080302232758</lastUpdated> </versioning> </metadata>
Note that this metadata is actually the metadata merged by Nexus from both the release and snapshots repositories that house the dependency plugin. Notice that LATEST is 2.1-SNAPSHOT, while RELEASE is 2.0. This is one reason why we recommend not combining snapshots and releases in the same repository. It is also why if you are add the apache or codehaus snapshot repositories to your settings you can get some odd behavior.
Every time a new release is pushed out, this metadata gets updated. Maven by default won’t look for a new LATEST if you already have a version of the plugin in your repository. That means a few things. First, it means that if we release a plugin you might not immediately pull it down. Second, it means that new members of your team are more likely to get new versions of the plugin than older ones…creating team platform inconsistencies. It is also why we sometimes tell you to try -U to look for new plugins.
So how do I avoid being subject to new plugin releases at inopportune times or having inconsistent results across a team?
It’s pretty easy actually: specify a version in your pom. If you have a large project or group of projects, this is not very scalable. The way to handle this is parallel to dependencies: define the version in build.pluginManagment and then omit the version in the build.plugins section.
During our Maven training classes, we recommend creating a single corporate pom from which all your projects inherit. You may have individual business unit poms and team poms, but the point is you inherit up to a central pom where you can control certain things, particularly plugin versions.
Ok, now I know how to control my plugin versions, how do I know which versions I want?
Good question and there isn’t a great answer right now. The best way would be to use the new enforcer plugin to require all plugins are locked down. If it finds a plugin in use that isn’t locked down, it will tell you and it will tell you which plugin you are currently using. Unfortunately this is only available in the latest snapshot…but I promise to get it released shortly.
In the meantime, the best way to go is to look in your local repository at org.apache.maven.plugins and org.codehaus.mojo. Record the plugins you find there and use the highest release. If you want to see what the most recent version in central is, then search or browse for your plugin on our public Nexus instance and look for the highest non snapshot version.
So how does 2.0.9 fit into all of this?
Many users are not locking down their plugin versions for many different reasons. Because of this it is unfortunately common to see people having build issues pretty quickly after a plugin release.
For a long time, the Maven team resisted locking down the plugins in lieu of a better solution and user education. One of the prime reasons was as I mentioned earlier, forcing plugins to have a declared version was not newbie friendly. Unfortunately the better solution has yet to materialize and the users continued to have trouble.
Recognizing that we had to do something to ease the pain, we came up with a fairly simple solution: provide default versions in the pluginManagement section of the superpom. We are, in effect, doing exactly what we teach in the classes. The benefit of doing this is that now core plugin versions will not “randomly” change on you unless you change your Maven version. Because local poms override inherited poms, this has no impact on builds that are already locking down their plugin versions.
What’s the fine print?
There are a few gotchas.
- It’s not practical for us to track all the plugins in the Maven universe. What we have locked in the super pom are all plugins injected by the default lifecycles and a couple other common ones like assembly and dependency. Everything else is still subject to LATEST updates.
- You won’t get plugin updates for these core plugins at all until you upgrade Maven.
- Your build may not be reproducible in the future if you’re using a new version of Maven because the plugins will likely be different.
- If you upgrade to a new version of Maven and your build breaks, it won’t be immediately apparent if the core caused the issue, or if it’s one of the plugins that changed
For these reasons and more, we highly recommend that you start taking control of your plugin versions and locking them down. This way you can try out one new plugin at a time, adjust if needed and then lock it. Once the 1.0 version of the enforcer plugin gets released this will be much easier to deal with. I’m also planning to share the code with the help plugin to make something like help:current-plugins.
There are several other exciting changes in 2.0.9 that are highlighted in the release notes.
In the meantime, the plan for 2.0.10 is laid out here and we are moving along, focused on killing regressions from older versions and fixing the popular issues so please vote on your favorite (or resented) issues.