Category Archives: Java

Imported from Pebble

Creating a Custom Build Extension for Maven 3.0

In the process of testing the Maven 3.0 release that’s being voted on, I wanted to try out the additional extension capability, and have a little fun with it in the process.

The result is an old friend of mine:

[INFO] Scanning for projects...
[INFO]  __  __
[INFO] |  \/  |__ _Apache__ ___
[INFO] | |\/| / _` \ V / -_) ' \  ~ intelligent projects ~
[INFO] |_|  |_\__,_|\_/\___|_||_|  v. 3.0
[INFO] 
[INFO] --------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] retro-example
[INFO] retro-example-1
[INFO] retro-example-2
[INFO]                             

This is a trivial example of course, but it shows that you can jump into the startup process much earlier than in the past. This is useful for those that want to extend Maven in a consistent way for a given project or type of project. I believe it is already in use by Tycho, and is a likely mechanism to simplify and enhance NPanday in the future.

While plugins and extensions could already offer additional components, it is now possible load components from within a project that can be set up before the build starts at all. The feature would most often be used to perform additional validation or processing of an entire set of projects in the reactor before they are executed. It is possible that it might also be used to adjust settings, execution properties or dependency resolution – though bearing in mind that these may already have been used to load the projects.

The above example makes use of the afterProjectsRead method (the whole project is in Subversion):

package org.apache.maven.examples.retro;

import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.RuntimeInformation;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;

@Component( role = AbstractMavenLifecycleParticipant.class, hint = "retro" )
public class RetroMavenExtension
  extends AbstractMavenLifecycleParticipant
{
  @Requirement
  private Logger logger;

  @Requirement
  private RuntimeInformation runtime;

  public void afterProjectsRead( MavenSession session ) {
    logger.info( " __  __" );
    logger.info( "|  \\/  |__ _Apache__ ___" );
    logger.info( "| |\\/| / _` \\ V / -_) ' \\  ~ intelligent projects ~" );
    logger.info( "|_|  |_\\__,_|\\_/\\___|_||_|  v. " + runtime.getApplicationVersion() );
    logger.info( "" );
  }
}

There are a couple of things to note here, particularly if you are familiar with writing components for Maven. Firstly, there are now some real annotations to use instead of the Javadoc-based version (though both would continue to work). This example still uses the Plexus annotations and the generated descriptor from the corresponding POM, though in the future it could use the JSR-330 equivalents.

Obtaining a logger is much easier than before, using a simple @Requirement to inject it instead of the LogEnabled interface or abstract class. Other requirements (in this case, the legacy RuntimeInformation class) continue to be injected as they have before.

The rest is self explanatory – based on the “role” and the abstract class, the method is called by the Maven core after the projects have been assembled but before they have been sorted and executed. We just output the ASCII art, however the method has the MavenSession object available to it to obtain the projects, as well as execution properties, repository access and settings.

To use the extension in a project, the following would need to appear somewhere in the POM hierarchy:

<build>
  <extensions>
    <extension>
      <groupId>org.apache.maven.examples</groupId>
      <artifactId>retro-maven-extension</artifactId>
      <version>1.0-SNAPSHOT</version>
    </extension>
  </extensions>
</build>

It’s worth noting that Maven 3.0’s extension handling and classloading is significantly better than Maven 2.x – you can now feel relatively free to use extensions and plugin dependencies in a multi-module project without conflicts.

That’s it! Every Maven command on a project with the extension will carry the banner lost for the last 5 years.

Maven Release Plugin awaits your testing

Somewhat dwarfed by Benjamin sneaking in the Maven 3.0 release vote 15 minutes later, the Maven Release Plugin 2.1 is currently being voted on.

It includes a handful of changes, most notably MRELEASE-530 to work better with Git.

The release plugin has a history of being a bit fickle across releases, so if you’re using the latest version, please try it out!

The biggest task ahead for the plugin is a thorough cleansing of the JIRA project. Even a cursory glance shows a significant number of duplicate, outdated, or out of scope issues. Hopefully that is something to revisit beyond ApacheCon next month.

John Smart on Hudson and “The Tools You Should Be Using”

This morning at JavaOne I took the opportunity to catch John Smart’s first talk on Advanced Hudson Usage. Not that I’m thinking of switching, of course 🙂 I was keen to compare how he handled several tasks in Hudson to how we’ve been doing similar things with Continuum.

It was an interesting talk for anyone looking at build management in general, highlighting the need for feedback, visibility and delivery; and how to work with different tools all through the development spectrum. Some details from the talk are on the Hudson live blog.

True to his form from Java Power Tools, John spent some time highlighting those other tools that everyone should be using. The responses particularly caught my attention. There were plenty of people in the room using Maven, which wasn’t surprising. However uptake on others was lower. Who is using an enterprise repository manager? Several hands, but not close to being all of the Maven users. Checkstyle, FindBugs? Sonar? Failing the build on quality checks? Only a handful I could see in each case. Automated deployment? Only moderate usage. Distributed builds? Described as the feature all self-respecting build server should have, there were again very few people using it in the room.

John’s response to many of the “are you using… ?” questions was a strong “You should be!”. I certainly agree, and having had many of these in place in varying degrees for several years, I often take for granted that they are the first thing to set up on a new project.

The amount of work and resources needed to get them all up and running, and working together seamlessly, needs to become easier. In our environment, even though we had a well integrated set of tools, we faced challenges with scaling when creating several new projects and managing multiple branches, and going the last mile on very frequent patch releases.

That was the motivation for what has gone into Maestro 3 this year, and the responses at the conference so far give me strong encouragement that we’ve been heading in the right direction. Instantly setting up integrated Maven, Continuum, Archiva, Sonar, Selenium and deploying the application bundle through a single UI was the first step, and we now have the basis for greater consistency and reuse for project set up and configuration through Maestro compositions. We’re now gearing up for more frequent build and test cycles over distributed agents from both our private cloud and Amazon EC2.

MaestroDev at JavaOne next week

After being in “stealth mode” for some time, MaestroDev is launching something new at JavaOne next week.

In the next few days, we’ll be unveiling our new website, with information on what we’ve been working on recently, and the latest of our news and upcoming webinars on software build, test, release and deployment infrastructure for Maven projects.

At JavaOne, we’ll have a booth where we’ll be discussing the company and showing off a sneak preview of the latest development in the upcoming release of Maestro 3. Be sure to come by and say hi!

It has been a few years since I’ve been to JavaOne and this year will obviously be a little different. I’m not sure what to expect just yet, but looking forward to it, and hopefully catching up with a few people. And while conferences are exhausting enough, it’ll be nice to be out of the crazy busy mode that has been the last few months!

Updated Multi-module Support for Maven Release Plugin

Last week Dennis started things moving to have another release of the Maven Release Plugin. The release process should start very soon, so please join us on dev@maven.apache.org to help test it!

This is certainly a nice one to have out the door, not only because of the length of time since the last release but because it fixes some important bugs (Subversion 1.6 support for starters), and improves multi-module support.

Having been bitten by the latter category myself very recently I took the opportunity to get a couple of changes in.

Support for flat directory multi-module projects

This highly requested support was actually added by Deng way back in May last year, but it was only recently that I started using the new version of the plugin and discovered a small corner case I jumped in and made a couple of improvements and fixes.

While I would always recommend using a typical hierarchical Maven multi-module project, there are a number of existing projects using the flat structure, particularly in non-Java environments. It’s good that the release plugin can now support anything with a common trunk.

This means that projects like the following will now release correctly (run from the parent directory):

.
|-- release-parent
|   `-- pom.xml
|-- release-module2
|   `-- pom.xml
`-- release-module1
    `-- pom.xml

Not requiring artifacts to be in the local repository before releasing

This controversial issue has popped up a number of times and proven to be a real nuisance in releases, where a multi-module project needed to be built locally before it can be released (including the preparation test, that makes 3 full builds!), or at best spouted a large number of warnings about missing dependencies on the artifacts it was yet to build.

In the end here we decided to revert to the original behaviour and accept the limitations that came with, while making the typical release faster and easier. The release:prepare-with-pom goal has been added to cater to the use case for which the dependency resolution was put in place originally. With this intended to be the 2.0 release of the plugin, we can stick to this behaviour going forward.

In the future, Maven 3.0 has added additional capabilities for plugins to operate with their modules without building them first, which will allow a unified and enhanced release:prepare goal once more, but in the mean time we’ve opted to put in place the best solution for the majority of Maven users today.