Archive

Archive for April, 2008

How to override a plugin’s dependency in Maven

April 23rd, 2008 By brian
Comments Off

Maven 2.0.9 introduced the ability to override a dependency used by a plugin. This is handy when you want to use a newer checkstyle, pmd, etc jar than is included by default in the plugin.

How you go about doing this actually depends on your use case because of an oversight in the Maven 4.0.0 model used by the Maven 2.0.x versions.

If you are using a plugin as a normal build plugin (as opposed to a report) then you will have it bound similar to this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>2.1</version>
  <executions>
      <execution>
        <id>check my sources</id>
        <goals>
          <goal>check</goal>
        </goals>
        <phase>compile</phase>
      </execution>
  </executions>
</plugin>

This version of the maven-checkstyle-plugin will use checkstyle 4.1 by default. If I wanted to use version 4.4 instead, I simply add a dependency block inside my plugin block like this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>2.1</version>
  <executions>
      <execution>
        <id>check my sources</id>
        <goals>
          <goal>check</goal>
        </goals>
        <phase>compile</phase>
      </execution>
  </executions>
  <dependencies>
     <dependency>
        <groupId>checkstyle</groupId>
        <artifactId>checkstyle</artifactId>
        <version>4.4</version>
     </dependency>
  </dependencies>
</plugin>

That was easy, right? As long as the new version you have introduced is api compatible with the version the plugin was linked against, you should be good.

Now, what about reports? Well unfortunately, the Model used in 2.0.x doesn’t allow dependencies to be specified inside the reporting block (MNG-1948)

In the process of creating the samples for this how-to, I discovered that the extensions don’t override the reporting plugin dependencies, so unfortunately there isn’t a way to override them. Stay tuned as we investigate how to deal with this.

Update: There is a way to make this happen with reports. In the example below, I removed the execution from the plugin block and added the plugin as a report. It seems that the dependency is inherited when the plugin is used in reporting. Not quite obvious, but here’s what it looks like:

<build>
   <plugins>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
         <version>2.1</version>
         <dependencies>
            <dependency>
               <groupId>checkstyle</groupId>
               <artifactId>checkstyle</artifactId>
               <version>4.4</version>
            </dependency>
         </dependencies>
      </plugin>
   </plugins>
</build>
<reporting>
   <plugins>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
         <version>2.1</version>
      </plugin>
   </plugins>
</reporting>

Checkstyle makes it easy to test this behavior because it writes out the checkstyle version in the results:

<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="4.4">

How-To, Maven

Maven: Week in Review Episode I

April 19th, 2008 By tim
Comments Off

Let us know what you think. (Known issue, the music levels are too high, we’ll fix that next week…)


powered by ODEO

Links from this recording:

News, Sonatype

How to share resources across projects in Maven

April 17th, 2008 By brian
Comments Off

There are a few ways to share resources across multiple projects or modules:

In this blog I’ll show how to do the second option since in my opinion, it is currently the most stable and flexible. In the future, I’ll try out the maven-remote-resources-plugin and write up a tutorial.

The assembly plugin is a bit complicated but it can also be very powerful when you find a few good examples to get you started. I felt it was important enough to understand assembly that I made it a pop-quiz lab for the Maven Training we provide.

At the end of this post is a zip file that contains the files described…so don’t worry about copying everything verbatim and focus on the why and how

I’m going to show how this is done in a multi module project, so the first thing we need is the top level parent pom (there’s probably an archetype for this but I just grab one from some random project and hack it up):

<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

<groupId>com.sonatype</groupId> <artifactId>resource-sharing</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Resource Sharing Parent</name>

<build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-2</version> </plugin> </plugins> </pluginManagement> </build> <modules> <module>resource-consumer</module> <module>assembly</module> </modules> </project>

In an enterprise, you will probably want this to inherit from your corporate pom. The only thing particularly interesting about the pom above is that I have declared the versions of the plugins I’m using in pluginManagement. Read more about this topic in my previous entry. I have also inverted the modules list to show that Maven is smart enough to reorder modules based on declared dependencies (this is another FAQ).

The next step is to create the module that will zip up the resources to be shared. I’m going to do this using the maven-assembly-plugin to zip up src/main/resources from my shared-resources project. The assembly descriptor in src/main/assembly/resource.xml to do this is pretty small:

<assembly>
  <id>resources</id>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <fileSets>
    <fileSet>
      <directory>src/main/resources</directory>
      <outputDirectory></outputDirectory>
    </fileSet>
  </fileSets>
</assembly>

We just told the assembly plugin to make a zip using a classifier of resources (more on this below). It will pick up the contents of src/main/resources and include them in the root of the zip. By default, assembly will create a subfolder with the artifactid-version as the name, so we turn this off by specifying the empty outputDirectory element.

Now we need the resource to include. While we’re at it, we’ll show some resource filtering. In src/main/resources/Readme.txt place:

This Readme is included in ${project.artifactId}-
${project.version}.${project.packaging}

The contents of ${} will be replaced by the correct values from the pom. Note: the old syntax was ${artifactId} or ${pom.artifactId} and these are still incorrectly being used. The correct syntax to dereference a pom value is ${project.xxx}.

<

p>The next thing we need is the pom.xml to do the work in the assembly module:

<

p>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.sonatype</groupId>
        <artifactId>resource-sharing</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

&lt;artifactId&gt;shared-resources&lt;/artifactId&gt;
&lt;packaging&gt;pom&lt;/packaging&gt;

&lt;name&gt;Shared Resources Bundle&lt;/name&gt;

&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;make shared resources&lt;/id&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;single&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                    &lt;configuration&gt;
                        &lt;descriptors&gt;
                            &lt;descriptor&gt;src/main/assembly/resources.xml&lt;/descriptor&gt;
                        &lt;/descriptors&gt;
                    &lt;/configuration&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

Here we have used a pom packaging project to get an empty lifecycle pallet. We bind the assembly:single goal to the package phase and point it at the descriptor. Note that no version is specified here because we already locked it down in the parent pom’s pluginManagment section. Be sure not to bind the assembly:assembly goal in a phase because this forks the build and can generally cause a mess of recursive builds.

So far we have managed to bundle up the resources into a zip that can be versioned and deployed to a Maven Repository Manager. So far, so good. Now we need to get those resources where we actually want them. To do this, we will use the dependency:unpack-dependencies to fetch the bundle and unpack it to the projects that need it. The pom to do it looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

<parent> <groupId>com.sonatype</groupId> <artifactId>resource-sharing</artifactId> <version>1.0-SNAPSHOT</version> </parent>

<artifactId>resource-consumer</artifactId> <packaging>jar</packaging>

<name>Resource User A</name>

<dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>shared-resources</artifactId> <version>1.0-SNAPSHOT</version> <classifier>resources</classifier> <type>zip</type> <!-- Make sure this isn't included on any classpath--> <scope>provided</scope> </dependency> </dependencies>

<build> <resources> <resource> <directory>${basedir}/src/main/resources</directory> </resource> <resource> <directory>${project.build.directory}/generated-resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack-shared-resources</id> <goals> <goal>unpack-dependencies</goal> </goals> <phase>generate-resources</phase> <configuration> <outputDirectory>${project.build.directory}/generated-resources</outputDirectory> <includeArtifacIds>shared-resources</includeArtifacIds> <includeGroupIds>${project.groupId}</includeGroupIds> <excludeTransitive>true</excludeTransitive> <!--use as much as needed to be specific...also scope,type,classifier etc--> </configuration> </execution> </executions> </plugin&gt </plugins> </build> </project>

The first thing we did was add our resource bundle as a dependency of this project. This is done to tell Maven about the dependency so that the bundle is created before it’s needed. We could have used dependency:unpack to do this without declaring a dependency but this causes other issues when used inside a multimodule build. Notice that I used a property to avoid having to hardcode the groupId of my sibling dependency. I did not do this for the version as it used to cause problems with SNAPSHOTs when deployed. I think it has been fixed but I haven’t tested it yet. Also note that the classifier matches the id used in the assembly descriptor above.

The next thing we’ve done is add the ${project.build.directory}/generated-resources as a resource and enabled filtering (note the use of a property and not hard coding of /target/). We have to re add the default resource of src/main/resources because it will get lost otherwise.

Then we bind the dependency:unpack-dependencies goal to the generate-resources phase (again leaving the version to be picked up in pluginManagement). The unpack-dependencies goal starts with a list of all dependencies of this project. Since we are only interested in one, we can use the various filters to narrow it down. Here I have filtered on the group and artifact ids and excluded all transitive dependencies. I could have also added scope, classifier and type if I felt it was needed. I have told the plugin to extract the contents of the zip to ${project.build.directory}/generated-resources (the same location I added as a resource above).

Now, to make this all happen, I only need to go up to the root of my project and execute mvn install. (package is the minimum to make the zip that unpack will need to find but I recommend just using install when working with multi-modules…it will save you lots of grief).

Since I’m a skeptic, I’m going to go into resource-consumer/target and unpack the jar. In the root of the jar I should find a ReadMe.txt with the following content:

This Readme is included in resource-consumer-1.0-SNAPSHOT.jar

Note that my properties were replaced with the values of the project that did the filtering. This was an extreme example as you may not always want to filter the unpacked values, but that’s even easier…just tell dependency where to drop the files and you’re done. If you’re working with wars, you can just drop the files into ${project.build.directory}/${project.build.finalName} and the war plugin will pick them up and include them in the final war.

This assembly sharing technique is also useful for sharing checkstyle and pmd rules. The only difference in those instances is that you don’t actually need to unpack the file. Instead of making a zip, make a jar and then add the jar in a dependency block inside the plugin declaration. If you are using those plugins as reports, you need to add the jar as an extension in the pom (report.plugins.plugin doesn’t allow a dependency). Then the plugins will look for and find your rule file on the classpath

Download the sample project files.

How-To, Maven

Writing a Book with Maven: Part I

April 14th, 2008 By tim
Comments Off

DISCLAIMER: In this post, I express my own, somewhat controversial, views about Doxia and APT. These are solely my own views and you should not assume that they represent an official statement from Sonatype.

This Maven Book is created using Maven. Everything you see is produced using Springer’s plugin: http://code.google.com/p/docbkx-tools/ - I don’t pass in all of the configuration variables via the pom.xml. We have two stylesheets html_chunk.xsl and xslfo.xsl which help us print out a nice looking PDF and web site from the book. In the next part of this series, next week, I’m going to start blogging about the Maven project we use to manage the book. By next week, I’m going to try to have a Maven archetype ready for people who want to produce a book with Maven. I might even put a chapter in the book about using Maven to create a book (recursion). Ultimately, I’d like to help start a few projects that will make it easier for people to write books using the same technologies we use to publish this book. We need to get more developers writing good content, there are too many technical books being written by people who haven’t had a day of real coding experience.

DocBook, WTF?

We use DocBook. The original idea was to use APT, but once I started working on the book, I insisted on DocBook to the surprise of many people involved with the effort. In this post, I explain why I think DocBook is the best choice for writing a book.

I’m going to spoil the party for APT lovers. APT is impossible. I’m convinced that APT is the reason why most Maven documentation and many Maven sites are terrible things to try to read. I’d encourage anyone trying to use the Maven Site Plugin to dump it and start using the XSite plugin. Don’t be afraid of HTML and Markup, Maven sites would, in general look natural and simpler if you didn’t have to suffer through all the canned copy and left navigation menus. It is impossible use APT to write a book with styled cross-references, a good index, appropriate in-line styles. The ability to differentiate between a listing of source code and numbered examples, variable lists, the differences between a chapter and a part are a preface. All of these things come with DocBook.

That being said DocBook tools are a terrible curse. The editor I use is XMLMind. Not only is XMLMind not free, it is about as usable as Emacs on a keyboard that has a broken Meta key. But, you get used it, and you learn to be productive. It takes a year, you initially swear it off, but then you come back to it and admit defeat by purchasing it and learning how to convince it to cooperate. In two years time, you’ll start to respect XMLMind and you might even start to customize some of the key bindings. In other words, it ain’t easy. But, this brings me to my next point…

…writing a book is not easy

When a bunch of developers (I still consider myself a developer, not a writer) get together and decide to write a book, there’s this underlying tension. A developer’s job is tough enough, they don’t want the writing process to start siphoning already scarce time off of the development cycle. The initial reaction is to choose some technology like APT because it is easier to write simple things with simple markup. This works for a while, you’ll write a few chapters and you might even start to develop innovative little plugins to including source code, etc. But, as the content grows in size, and you start getting ready for print production, you’ll start to think about things like:

Cross-references
A large book without cross-references is about as useless as it gets. If I’m in Chapter 5 Section 3 and I want to reference Chapter 1 Section 1.2, and I don’t have a way to exactly specify an element in a document, what happens when I move a chapter around or when I want to insert a section before Section 3. Sure, I can develop a facility within some Doxia engine to allow me to reference a section of a document, but then you’ll want to do things like customize the text of the reference. Maybe half the time, I’ll want to say “See Section 15.1 for more info”, but just as often I might want to say “See Section 1.5 Aggregating Stuff for more info”. The point here is that cross-references are increasingly important for both the PDF, HTML, and print output, the only way to equal what comes out of the box with DocBook is to add more hacks to APT and customize the engine that reads it.
Inline Styles
This is probably the one thing that throws most developers-turned-writers into a tailspin. The idea that every command, classname, code reference, variable reference has to have a different inline style. This takes most people a few weeks to get the hang of, but once you start doing this, you’ll start to realize that it is essential to making readable technical content. Pickup any O’Reilly book, and you’ll notice that it contains a heavy amont of inline styling - Classnames are in a fixed font, they are differentiated from commands on the command-line. We don’t just do this because we like to be fancy, we do this because it is a subtle hint to the reader that eases comprehension. It is also something that requires different markup elements in the book’s source. There are classname, methodname, variable, code elements in DocBook to handle this. Not so in APT Because APT is solely focused on presentation, you can’t embed semantic meaning within it. You can’t say, “this is a classname”; instead, in APT you say, “make this italic” or “make this bold”.
Print Production
The publisher I’ve worked with formats the book in DocBook before they send it off to the presses. There’s a lengthy production process during which the book is converted to DocBook (if it isn’t already in DocBook) and someone is going to go through and make sure that the book has all the right inline styles. Then someone is going to go through and markup all the index terms (indexing is an arduous and mind-melting experience BTW). I prefer to produce a product that doesn’t require too much manual futzing with after I deliver it. I understand that the production dudes need to tweak the content a bit, but, I prefer the idea that my stuff doesn’t have to go through some sort of filter before it gets to the real content. More on this in later parts of this series…
Formatting for Print/Web/PDF
Sure, I understand that I can get some APT stuff to spit out a PDF and a web page. But, can I tell it what section level I want it to descend to when computing the contents of a table of contents? Can I put a watermark on the output and put a disclaimer in the header of the preface to signify that the output is an alpha release? (something I need to do) Can I generate endnotes? how about footnotes? I could go on and on and on an on about things DocBook can do that APT can’t. It all really boils down to tools and the fact that, with DocBook, I’m capturing more than just syntax - DocBook is semantic and there are a whole host of tools out there that let me convert that output to good looking output. I’m sure someone is going to comment that all of this is possible with some sort of customized Doxia plugin (see previous, I think Doxia should be thrown overboard.)

You could hack up APT so much so that it closely approximates DocBook. You could muck around with the various Maven plugins involved in the process to make it easy to include code samples and snippets….. or, you could use the tools and technologies which already exist. I’m no big fan of reinvention, so for me, the solution was to use DocBook. Furthermore (ugh), hacking APT to the point where it supported a featureset similar to DocBook would’ve meant making APT more like DocBook. By definition, I don’t think you can write a book which requires this much semantic stuff in a wiki-like format without making the wiki-like format more trouble than it is worth.

…stop trying to make it easy…

Even when I wrote Jakarta Commons Cookbook in Word, it was far from easy. There was an ultra-nifty (but very complex and unstable) set of VB macros which were used to manage cross references and inline styles. There was a whole host of keyboard shortcuts, etc. For a 400-page book, I had to split the document into chapter DOC files and have every document open in Word in order for cross references to properly render. It wasn’t an uncommon experience for Word to just blow up and refuse to respond. That was about four years ago, in the intervening years there have been various efforts to simplify the process and move to different tool platforms.

Books have been written in OpenOffice. (And, yes, there are books that have been written in APT.) A few people have tried to write books using collaborative web applications. There has been this persistent idea that people could collaborate on a Wiki and produce a great book, etc….

For me, the most difficult part about writing a book isn’t the technology used to write it. From a wiki-like markup to etching every word on to a stone tablet, for me the most difficult part of writing is the process itself. I use a difficult tool to write with XMLMind, but I spend most of my time writing, and rewriting, and rewriting, and rewriting, and proofreading, and rewriting, and rewriting……

And, writing about technology for a tech-audience isn’t easy. I guess what I’m trying to say is stop using tool selection as an excuse to procrastinate and get down to the business of writing. Writing isn’t easy; in fact, it is just as difficult (maybe a little more difficult) than writing code. Don’t shy away from using professional writing tools even if they are not easy. Writing a book isn’t easy, it’ll drive you crazy. I promise.

Book, How-To

Maven 2.0.9 Released

April 10th, 2008 By brian
Comments Off

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.

Maven, News

Sonatype Nexus 1.0.0-beta-2 released

April 8th, 2008 By brian
Comments Off

Sonatype Nexus 1.0.0-beta-2 has now been released. A list of the changes can be found here. If you are upgrading from beta-1, be sure to see the new upgrade section in the Nexus chapter of our Maven book.

Nexus is a Maven repository manager that is able to host your internal repositories, proxy downloads from external repositories, generate indexes consumable by M2eclipse, and if you ask nicely, it will even do your dishes!

Learn more about Nexus

Maven, News, Nexus

Quality is not accidental

April 8th, 2008 By brian
Comments Off

I’ve had plenty of opportunities to manage releases of products in my career. As I mentioned in an earlier post, most of them were large mission-critical enterprise applications. Open source projects are different beasts entirely, but they don’t have to be. A little bit of Enterprise rigor combined with the vast resources of the community can reap great rewards.

Lately the Maven project has been taking a lot of heat from various sources about stability and over-all quality. For the most part, they were right. The Maven team is very strong and certainly no one intends for these problems to happen, but ultimately they were.

In a well run commercial project, you have a team of QA engineers dedicated to validating fixes and checking for regressions. Unfortunately no matter how hard you test and identify regressions, business pressures often force a release to occur before it’s truly ready.

In an OSS project, the team is typically made up of developers and not professional testers (or docs writers). As such, you tend to end up with lots of code and less than stellar testing coverage. However, if you expand the concept of the team a bit to include the user community at large (aka The Community), you can easily smoke the commercial equivalent for a couple of reasons:

  • The user community is comprised of a nearly limitless number of expert users who are highly motivated to check for regressions
  • Each user in the community brings a slightly different set of use cases to the testing effort
  • The absence of business pressure for a release can be a blessing if harnessed correctly.

During a review of the open issues while planning 2.0.10, I became aware that a significant number of open issues start with “this used to work until 2.0.[x]“. I became frustrated and a little embarrassed to realize how bad of a regression problem we had going on.

At that point I decided that my personal priority for 2.0.9 had to be No more regressions.

The normal release process for Maven is to stage a release, email the dev list and wait for votes or show stopper issues to occur. The norm for most releases is 72 hours, but with Maven core releases it was common to let it bake for a week or more. Based on history, I was positive that the first few attempts wouldn’t make it through, so we started with a “pre vote” instead of a vote email.

It seemed that each “pre vote” staged release we posted for dev list testing showed yet another how come no one noticed that? regression. It became apparent that we needed more than ever to harness the power of the full community to squash these regressions. Since tossing out multiple versions all called “2.0.9″ to such a wide audience was clearly a bad idea, we started appending -RC[x] to distinguish them. Additionally, we needed to have a set of operating parameters to guide this broad level of testing, lest we have chaos in the flood of bug fix requests.

The gist of the operating parameters was:

  • We won’t fix more issues unless it’s a demonstrated regression from the previous version. (2.0.8)
  • We will fix all regressions identified unless fixing it is riskier than leaving it.
  • All changes will be accompanied with a core Integration Test.
  • Community participation will drive the quality of this release.
  • We will continue this progress as long as it takes.

That last item relates specifically to the lack of business pressures to force a premature release. Being OSS allows us to harness the immense power of the community for as long as it takes to get the release right.

So far we’ve gone through 8 release candidates, and, as a team, we were able to correct every regression identified, something I wasn’t sure would be possible. The official release is now staged awaiting a last check and formal vote. If all goes well, the release will be out later this week.

The feedback received on the new process has been overwhelmingly positive and the level of testing by users was surprisingly high for the first try. A special thanks to all of you that tested and provided feedback, even if it was just confirming that everything looked good. Several users went through the effort to validate all eight of the RCs on corporate CI systems and that’s no small feat.

Going forward, I’m hoping to be able to put out more regular core releases and by holding the No regression mantra from the beginning, future releases should be easier. As promised the lessons learned from this release will be codified into a new formal release procedure. I’m currently toying with introducing the idea of milestone releases for regression testing should any future release go beyond a month or so since the last release.

Only time will tell if 2.0.9 stands out from all the predecessors in terms of quality, but it feels like we’re on the cusp of a new era. WDYT?

Community, Maven, Strategy

Sonatype’s Nexus 1.0-beta-1 Released

April 4th, 2008 By jason
Comments Off

After many months of alpha testing we are tickled pink to announce the 1.0-beta-1 release of Nexus. Tamás Cservenák, Brian Fox, Eugene Kuleshov and Justin Richard have been working very hard to bring Maven users something we feel will benefit the whole community. In an unbelievable twist of fate, this might be the first Maven-related project that has documentation with its first releases! We have a website with some information about Nexus which you can find here:

http://nexus.sonatype.org

And Tim O’Brien has written a chapter on Maven repository management which covers all the basics that people will need to get started with Nexus. We’ll have a few more cool announcements to make about Nexus shortly, but people are probably most interested in how to get started, where they can download Nexus, and if there are any mailing lists to join. You can surf around the site, but here are the most relevant links.

http://nexus.sonatype.org/getting-started.html http://nexus.sonatype.org/download.html http://nexus.sonatype.org/mailing-lists.html

We look forward to feedback from users, and you’ll definitely be hearing more from us about Nexus!

Thanks,

The Sonatype Team

Nexus

Nexus Repository Manager 1.0.0-beta-1 Released

Nexus is the next generation of the popular Proximity repository manager software for use with Apache Maven. This is the first public release of Nexus, and I believe it marks an important milestone in the practice of building software.

I’m not what you might call an early adopter when it comes to software. In the vast majority of applications I use, I know how to use less than 25% of the features. A long time ago, I realized I was spending too much time trying to keep the technology (software, hardware, configurations, whatever) going to get anything done in a reasonable amount of time. Today, my point of view is very pragmatic. For any new application, I generally ask myself what the software does that will make my life easier in concrete terms, and can I really depend on it to do these things reliably and with little or no babysitting. For instance, I generally don’t use the milestone releases of my IDE of choice, Eclipse; they’re simply not stable enough for me to be able to focus on the software I’m trying to write.

As a result of this viewpoint, you’re not going to hear me get very excited about beta releases of other people’s projects very often. You won’t hear me trying to sell you on the latest and greatest technology that probably overstates its capabilities. I’m not a big believer in the value contained in the promise of a piece of software, unless I have intimate knowledge of how it’s put together. In short, I’m not going to be your first choice for the job of technology evangelist.

Having said all of that, I do stand by my initial statement about Nexus. I do believe Nexus represents something new in the discipline of producing quality software. I can talk about the slick UI features that I love to look at; I can talk about how cool it is that you can reuse repository definitions in different groupings that themselves look like remote repositories to Maven; I could even talk about the fact that you can literally unzip and start Nexus with no configuration, and start using it immediately…which makes it incredibly easy to try out. But for me, these are all window dressing. What I really love about Nexus is how it puts its money where its mouth is. This is an application that just works. Period. For anyone in the software industry, you’ll know how rare this is.

I work with the guys who wrote, tested, and released Nexus, and having a chance to witness firsthand the use cases and quality control that went into this application, I can honestly say I’m really excited about this project. Maybe it means something that I’ve been developing the core of Maven for four years, and thinking almost exclusively of how to improve the way we build software for over three of those years; maybe it doesn’t. The good news is, you don’t have to take my word for it. Try it yourself. It’s dead simple to get started.

To download Nexus, visit the Nexus website, and click on the Download link. To learn how to start using Nexus, try the Getting Started link. For now, the best way to get started is to read the chapter on Nexus in Maven: The Definitive Guide; but it’s a good idea to bookmark the website as well, so you can find out how to tell us what you like, what you want to see but don’t, and what you might find that seems broken in this first beta release.

Please be sure to take it for a spin; I bet you’ll be glad you did.

Technorati Tags: , , , ,

News, Nexus

The m2eclipse project proposal at Eclipse: Maven married with Eclipse!

April 3rd, 2008 By jason
Comments Off

For Maven users interested in Maven integration with Eclipse, you might want to take note of the m2eclipse proposal submitted to Eclipse a couple days ago. This work is being lead by Eugene Kuleshov (also a Subclipse and Mylyn committer). You can discuss the project with Eugene and the rest of the team, in the newly created m2e newsgroup at Eclipse:

http://www.eclipse.org/newsportal/thread.php?group=eclipse.technology.m2e

m2eclipse