<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sonatype Blog &#187; best practice</title>
	<atom:link href="http://blog.sonatype.com/people/tag/best-practice/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sonatype.com/people</link>
	<description>Sonatype is transforming software development with tools, information and services that enable organizations to build better software, faster, using open-source components.</description>
	<lastBuildDate>Thu, 16 May 2013 18:53:09 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Nexus Tips: Disable Redeployment in Nexus</title>
		<link>http://blog.sonatype.com/people/2009/11/nexus-tips-disable-redeployment-in-nexus/</link>
		<comments>http://blog.sonatype.com/people/2009/11/nexus-tips-disable-redeployment-in-nexus/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 16:10:26 +0000</pubDate>
		<dc:creator>Brian Demers</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[nexus pro]]></category>
		<category><![CDATA[repository]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=3111</guid>
		<description><![CDATA[It&#8217;s a fundamental tenet of Maven that release artifacts never change once they are released. This is enforced in Maven by the fact that once a release artifact or POM is located in the local repository, Maven will never check for an updated artifact in a remote repository. Once an artifact is released, it is [...]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s a fundamental tenet of Maven that <b>release artifacts never change once they are released</b>. This is enforced in Maven by the fact that once a release artifact or POM is located in the local repository, Maven will never check for an updated artifact in a remote repository.   Once an artifact is released, it is considered a static, unchanging artifact.  If you release an artifact and then subsequently change it (intentionally or otherwise), you&#8217;re in for some fun as people will have different versions based on when they first retrieved it&#8230; that&#8217;s a situation not exactly conducive to a repeatable, standard build.   This blog post discusses a feature in Nexus 1.4 which can enforce this rule and help you avoid problems caused by the redeployment of release artifacts.</p>

<p><span id="more-3111"></span></p>

<p>To illustrate this problem, consider a 1.0 build of your product that depends on foo-1.2.jar.  It works great. Then you build 2.0 of your product which still depends on foo-1.2.jar.  Since then, foo-1.2.jar was patched and now breaks your application.  However the application still works for half of your developers because the original foo-1.2.jar is in their local repository and possibly proxied in another Nexus instance.</p>

<p>The solution is to release a new version foo-1.2.1.jar. (ie foo-1.2.2.jar or foo-1.2.1.1-jar), but that alone isn&#8217;t enough.   You want to make sure that you are using a repository manager that prevents someone from updating a release artifact once it has been published.</p>

<p>It has always been possible to stop people from doing this in Nexus but the solution was difficult to <a href="http://nexus.sonatype.org/about/faq.html#QHowdoIdisableartifactredeployment">explain</a>.    In the Nexus 1.4 release, we have reworked and simplified the interface to encourage this best-practive.</p>

<p>To disable redeployment, edit your repository and set the &#8216;Deployment Policy&#8217; field to &#8216;Disable Redeploy&#8217; then click save.</p>

<p><img class="alignnone size-full wp-image-3115" title="disable-redploy" src="http://www.sonatype.com/people/wp-content/uploads/2009/10/disable-redploy.png" alt="disable-redploy" width="422" height="140" /></p>

<p>Upgrading from a previous version of Nexus 1.4.0 will set this field to &#8216;Allow Redeploy&#8217;, so no existing repositories will be changed and the behavior matches previous releases. However the default value when creating a new repository is now &#8216;Disable Redeploy&#8217;.</p>

<p>When you use Nexus, you are not just using a capable repository manager, you are adopting the best-practice.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2009/11/nexus-tips-disable-redeployment-in-nexus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Summary of Maven How-Tos</title>
		<link>http://blog.sonatype.com/people/2009/04/summary-of-maven-how-tos/</link>
		<comments>http://blog.sonatype.com/people/2009/04/summary-of-maven-how-tos/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 18:18:17 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[m2eclipse]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=1939</guid>
		<description><![CDATA[We have a handful of Maven best practice and How-Tos documented in the blogs. Over time they get buried by newer posts, but the content is still just as relevant. Here is a summary of what exists:]]></description>
				<content:encoded><![CDATA[<p>We have a handful of Maven best practice and How-Tos documented in the blogs. Over time they get buried by newer posts, but the content is still just as relevant. Here is a summary of what exists:
<span id="more-1939"></span></p>

<ul>
    <li><a href="http://www.sonatype.com/people/2009/02/why-putting-repositories-in-your-poms-is-a-bad-idea/">Why Putting Repositories in your pom is a bad idea</a></li>
This entry explains how to properly manage repository definitions and why you shouldn&#8217;t declare them in your poms.
    <li><a href="http://www.sonatype.com/people/2009/01/best-practices-for-releasing-with-3rd-party-snapshot-dependencies/">Best Practices for Releasing with 3rd Party Snapshot Dependencies</a></li>
This entry describes how to most effectively create your own internal release of a snapshot dependency.
    <li><a href="http://www.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/">Maven Continuous Integration Best Practices</a></li>
This entry describes several techniques for running Maven builds from a CI system.
    <li><a href="http://www.sonatype.com/people/2008/05/maven-code-how-to-detect-if-you-have-a-snapshot-version/">How to Detect if you have a Snapshot Version</a></li>
This entry shows the code that Maven uses to detect a snapshot version. This is helpful if you have non-standard release versions to make sure they won&#8217;t be detected by Maven as a snapshot.
    <li><a href="http://www.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/">Optimal Maven Plugin Configuration</a></li>
This entry gives some tips on how to configure plugins in a way that makes it easier to understand what is happening in your pom.
    <li><a href="http://www.sonatype.com/people/2008/05/adding-additional-source-folders-to-your-maven-build/">Adding additional source folders to your maven build</a></li>
This entry shows how to use the buildhelper plugin to add additional source folders to your build. This is common if you have tools that generate sources that don&#8217;t have a maven plugin to add the source folder automatically.
    <li><a href="http://www.sonatype.com/people/2008/05/misused-maven-terms-defined/">Misused Maven Terms Defined</a></li>
This entry explains several terms that are often misquoted. It also specifically discusses classifiers and attached artifacts.
    <li><a href="http://www.sonatype.com/people/2008/04/how-to-override-a-plugins-dependency-in-maven/">How to override a plugin&#8217;s dependency</a></li>
This shows how you can override a plugin dependency in your own pom&#8230;for example if you want to use a newer version of a tool wrapped by a plugin (pmd, checkstyle, cobertura are common examples)
    <li><a href="http://www.sonatype.com/people/2008/04/how-to-share-resources-across-projects-in-maven/">How to share resources across projects</a></li>
This entry will show you how to share resources in a repeatable way without using relative paths in your poms. It also shows a technique for sharing checkstyle and pmd configurations across all your modules.
    <li><a href="http://www.sonatype.com/people/2008/04/maven-209-released/">How Plugin versions are determined</a></li>
This entry is actually part of the Maven 2.0.9 announcement, but explains how Maven determines which version of a plugin to use, and why you should use PluginManagement to control the versions yourself.
    <li> <a href="http://www.sonatype.com/people/2009/04/how-to-convert-from-ant-to-maven-in-5-minutes/">How to convert from ant to maven in 5 minutes</a></li>
    <li><a href="http://www.sonatype.com/people/2009/08/how-to-make-an-executable-jar-in-maven/">How to make an executable jar</a></li>
</ul>

<p><strong>Note: If you have suggestions for further topics, please leave a comment with your ideas.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2009/04/summary-of-maven-how-tos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why Putting Repositories in your POMs is a Bad Idea</title>
		<link>http://blog.sonatype.com/people/2009/02/why-putting-repositories-in-your-poms-is-a-bad-idea/</link>
		<comments>http://blog.sonatype.com/people/2009/02/why-putting-repositories-in-your-poms-is-a-bad-idea/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 19:30:34 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Sonatype]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[Book]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[repository]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=1647</guid>
		<description><![CDATA[I get this question frequently so it is time to write down my thoughts on the answer so I can stop repeating myself. Here&#8217;s the question: Should I put the urls to my repositories in my poms or in my settings? The short answer is: settings. The long answer is: it depends. There are two [...]]]></description>
				<content:encoded><![CDATA[<p>I get this question frequently so it is time to write down my thoughts on the answer so I can stop repeating myself.  Here&#8217;s the question:</p>

<p><em>Should I put the urls to my repositories in my poms or in my settings?</em></p>

<p>The short answer is: <em>settings</em>.</p>

<p>The long answer is: <em>it depends</em>.</p>

<p>There are two scenarios to consider here. Enterprise software (generally not published externally) and public software. Lets take Enterprise software first.   Continue reading this post for a full explanation of both scenarios.
<span id="more-1647"></span></p>

<h2>Enterprise</h2>

<p>In an Enterprise scenario, you will typically want to have a repository manager like <a href="http://www.sonatype.com/products/nexus">Nexus</a> sitting on your front lines. It will be proxying all external repositories and hosting your internal ones.</p>

<p>When Maven looks for an artifact, it walks down the list of repositories defined in the POMs and settings until it finds what it wants. If you define your repository manager as a repository in your POMs Maven will still fall back to the built-in Central repository when artifacts are not found in the repository manager.</p>

<p>One possible solution to this is to overload the &#8220;central&#8221; repository id and point this at your repository manager. This can work, but you would want to do this in your corporate pom so you don&#8217;t need to define it in every project you have. Once you&#8217;ve overloaded &#8220;central&#8221;, you have a <a href="http://en.wikipedia.org/wiki/Catch-22">&#8220;Catch-22&#8243;</a>. In a clean environment, you need to know where the repository is to find the parent POM &#8212; to tell you where the repository is. You will end up having to define this repository in your settings anyway just to bootstrap.</p>

<p>Simply redefining Central has a few other problems. Specifically, it doesn&#8217;t redirect repositories that may be defined in other POMs you include transitively. This causes a few problems: first, it will slow down your builds as Maven goes out to all the external repositories looking for artifacts&#8230;possibly even your internal ones that would never be found there.  Second, it means something may build for one developer but not another.  Third, it means as an organization you have no idea where your artifacts are coming from.</p>

<p>As an organization, you generally will want all your developers using the same set of repositories for their builds, and make all requests via a controlled mechanism. This is best accomplished with a mirrorOf * entry in your settings to redirect all lookup requests to your repository manager. It is not possible to define a mirrorOf in a POM. See this section of the <a href="http://www.sonatype.com/books/nexus-book/reference/maven-sect-single-group.html">Nexus Book</a> for examples of what a good setup will look like.</p>

<p>With all these things considered, you can see that defining the repositories in your poms doesn&#8217;t really help you much and generally just gets in the way.</p>

<p>This all presumes that your artifacts are not consumed externally. If they are, then you also fall into the next category. (They are not mutually exclusive)</p>

<h2>Open Source Projects</h2>

<p>If you are publishing your software and others will check it out and build it, then there are more points to consider. If all your dependencies are available in the Central repository, then you have nothing else to do. If however, you have artifacts that may exist only in your repository <em>(think snapshots of your parent POMs)</em>, or other third party repos, then developers will have a hard time building your source.  Only in this case does it make sense to add repository entries to your POMs. However, there are side effects to this that should be noted:</p>

<ul>
    <li>The entries you have defined will be <strong>burned forever</strong> into your released POMs. This means that, should the URLs change down the road, anyone consuming your POMs will face these broken URLs and have to track down the new ones manually.</li>
    <li>Each of these entries will end up in your consumer&#8217;s builds since Maven needs to check them all for missing dependencies. Maven currently isn&#8217;t able to tell when you introduce a repository which dependencies are supposed to be found there (and it gets worse when you consider transitivity).</li>
</ul>

<p>If the product of your build is a tool (like Nexus) rather than components used as dependencies, then adding the repository to the POM is fairly safe. In this case, it is unlikely others will depend on your artifacts directly in some other build, and the above concerns are nullified since presumably the new source would have the correct repository URLs.</p>

<p>If you are publishing jars that will be consumed by others, then you should think about getting them synced to the Central repository. This means that they will always be available to all users no matter what happens to your repository or URLs, and you won&#8217;t accidentally introduce new repositories to their builds.   Central will eventually reject POMs with repository elements for this reason.</p>

<h2>Summary</h2>

<p>So to sum up, if you want to have repeatable builds and good control over your organization internally, use a repository manager and use a mirrorOf entry in everyone&#8217;s settings.xml to point at that url.</p>

<p>If you are exposing your source and want to make it easy for others to build, then consider adding a repository entry to your POM, but don&#8217;t pick a URL lightly, think long-term, and use a URL that will always be under your control.  If your URL has to change down the road, make sure that you will always be able to track 404s and write the appropriate mod_rewrite rules to ensure that future builds will be able to find the appropriate artifacts.</p>

<p><strong>PS</strong>. If you got here from the Jfrog blog, then I suggest you read my <a title="response" href="http://java.dzone.com/articles/why-nexus-and-not-artifactory">response</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2009/02/why-putting-repositories-in-your-poms-is-a-bad-idea/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Best Practices for releasing with 3rd party SNAPSHOT dependencies</title>
		<link>http://blog.sonatype.com/people/2009/01/best-practices-for-releasing-with-3rd-party-snapshot-dependencies/</link>
		<comments>http://blog.sonatype.com/people/2009/01/best-practices-for-releasing-with-3rd-party-snapshot-dependencies/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 17:33:22 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[snapshot]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/?p=1486</guid>
		<description><![CDATA[The Maven Release plugin enforces best practices for releasing Maven artifacts. In summary, the release plugin performs the following steps: Validate no local changes against your SCM Validate that there are no SNAPSHOT dependencies Convert the modules to the to-be released version Ensure the build and Unit/Integration tests succeed Commit the changes to SCM, then [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://blogs.sonatype.com/people/wp-content/uploads/2009/01/maven.png"><img class="alignright size-full wp-image-1488" title="maven" src="http://blogs.sonatype.com/people/wp-content/uploads/2009/01/maven.png" alt="" width="180" height="77" /></a>The Maven Release plugin enforces best practices for releasing Maven artifacts. In summary, the release plugin performs the following steps:</p>

<ol>
    <li>Validate no local changes against your SCM</li>
    <li>Validate that there are no SNAPSHOT dependencies</li>
    <li>Convert the modules to the to-be released version</li>
    <li>Ensure the build and Unit/Integration tests succeed</li>
    <li>Commit the changes to SCM, then Tag the release</li>
    <li>Checkout the tag to a clean location and build/deploy the artifacts</li>
</ol>

<p>Dealing with failures on Step #2 is where I want to focus today.
<span id="more-1486"></span></p>

<h2>Background</h2>

<p>Lets step back a moment and give some background on SNAPSHOTS. In Maven, all artifacts must have unique coordinates comprised of Group, Artifact, Version (there are a few more like classifier and type that aren&#8217;t relevant for this discussion&#8230; <a href="http://www.sonatype.com/book">see the free maven book</a> for more info on these.)</p>

<p>By definition artifacts are either Releases or SNAPSHOTS. Releases are expected to be immutable and SNAPSHOTS are temporal. A SNAPSHOT version has the SNAPSHOT keyword in the version string like 1.0-SNAPSHOT. When these artifacts are deployed to a remote repository, the SNAPSHOT portion is transformed into a time-stamp (in UTC) and an incremental build number is appended. Thus 1.0-SNAPSHOT becomes something like 1.0-20090105.231034-52 when it&#8217;s deployed.</p>

<h2>The Problem</h2>

<p>The reason you can&#8217;t release an artifact that depends on a SNAPSHOT is that later on, this artifact may change or simply may not be available. (Remember, SNAPSHOTS are temporal)</p>

<p>If you are attempting to perform a release and you have dependencies on 3rd party SNAPSHOT artifacts, you will need to resolve this before moving on. The first thing you might try is revert back to the previous release, leading to Best Practices #1 and 2:</p>

<h4>Rule #1: Only use 3rd party SNAPSHOTS when absolutely necessary</h4>

<p>Use SNAPSHOTs temporarily to validate fixes but don&#8217;t commit your poms this way unless&#8230;</p>

<h4>Rule #2: If you do need it, record why you need it</h4>

<p>Preferably as a comment in the Pom, referring to a bug number.
Adherence to this rule will make it easy to determine if you actually need the new dependency. It will also make it easy to decide if you can work around it or could live without it.</p>

<p>Assuming you really do need it, you have a couple of choices. The first is to request a release of the artifact. Chances are though if you are at this stage of a release, it&#8217;s too late to wait.</p>

<p>The obvious alternative is to control your own destiny and release anyway.</p>

<h2>Not the solution</h2>

<p>A common anti-pattern is to find the exact time-stamp-build number of the SNAPSHOT you are depending on and put that as your dependency version. We refer to this as locking to a timestamp.</p>

<h4>Rule #3 Never release using the Time-Stamped snapshot</h4>

<p>There are several reasons why this is a bad idea.</p>

<ol>
    <li> First is that Maven and Maven Tools that mimic Maven properly are able to detect a SNAPSHOT based on the timestamp pattern. (See my <a href="http://blogs.sonatype.com/people/2008/05/maven-code-how-to-detect-if-you-have-a-snapshot-version/">previous</a> entry showing how this is done correctly.) The release plugin will still fail if you do this because it correctly understands you have SNAPSHOT dependencies. The plugin has a flag to allow bypass this check and people unfortunately use it far too often.</li>
    <li>Since Maven and related tools see these time-stamped artifacts as a SNAPSHOT, you will have to keep this artifact in a SNAPSHOT repository. This might be acceptable if you take that artifact and host it in your repository manager but you must remember to never delete it. This would be complicated if you wanted to share your release with people outside your organization.</li>
    <li>The dependency could disappear from the external repository. If you aren&#8217;t using a repo manager (What? Didn&#8217;t you get the <a href="http://blogs.sonatype.com/people/2008/11/nine-reasons-to-use-a-repository-manager-sonatype-nexus/">memo</a>?) then you are totally subject to the cleanup process of the external repository.Not a good place to be.</li>
</ol>

<h2>The Solution</h2>

<p>There are a few approaches to this that are acceptable. Which one you choose depends on your level  of paranoia. This process can be recursive if your SNAPSHOT dependency has other SNAPSHOT dependencies. They are all approaches to rule #4:</p>

<h4>Rule #4: Convert the SNAPSHOT version to a Release version and host it in your repository</h4>

<ul>
    <li><strong>Just deploy the artifact:</strong> The simplest approach to this is to take the SNAPSHOT binary artifact itself and deploy it to your repository. Remember to adjust the Pom.xml as needed. If you use <a href="http://nexus.sonatype.org">Nexus</a>, then you can upload via the UI and the artifact will be renamed based on the version you choose. (others can upload via the ui, but I&#8217;m not sure if they rename the file for you) If you use this approach, be aware that the artifacts produced by Maven have a MANIFEST that contains the SNAPSHOT version. Maven 3.x uses this for plugins and may refuse to use this artifact based on the version not matching what was expected. The trouble with this approach is that should you need to patch this artifact down the road, you don&#8217;t know exactly what sources produced it.</li>
    <li><strong>Build from the sources:</strong> The next approach (and this is my preferred method) is to checkout the sources and build the snapshot yourself. This way I know exactly what I have should I need to patch it later. If you are uber-paranoyed you can commit the source to your scm for posterity. If you trust the remote SCM (as I do for the Apache projects) then simply recording the scm revision used to retrieve the source is enough. You&#8217;ll need to change the versions of the artifacts in the POMS and then deploy it to your repository. I like to put the svn revision right into the artifact version such as 1.0-[my company name]-[svnid]. <a href="http://repository.sonatype.org/content/repositories/sonatype-apache-releases/org/apache/maven/maven-core/">Look at an example</a> of how we did this this for 2.1-SNAPSHOTS of Maven code used by <a href="http://nexus.sonatype.org">Nexus</a> and <a href="http://m2eclipse.sonatype.org">M2eclipse</a>.</li>
</ul>

<h4>Rule #5: Change only the version, not the groupId or ArtifactId</h4>

<p>When you make these new versions, resist the urge to change the groupid as well since this will change the coordinates and Maven wouldn&#8217;t detect collisions. You could end up with your copy and the official copy of the same dependencies in your build. Having changed only the version makes it much easier to switch back to the official public release when it becomes available.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2009/01/best-practices-for-releasing-with-3rd-party-snapshot-dependencies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven Continuous Integration Best Practices</title>
		<link>http://blog.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/</link>
		<comments>http://blog.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 04:46:15 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[ci]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[Hudson]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/?p=1393</guid>
		<description><![CDATA[Continuous Integration is a development best practice that you need to be using in your process; it is an essential part of an efficient Software Development Lifecycle (SLDC).   If you aren&#8217;t using it already, then you should start, now.   The main benefit of Continuous Integration is the ability to flag errors as they are [...]]]></description>
				<content:encoded><![CDATA[<p><img class="alignright size-thumbnail wp-image-1401" title="maven-ci-best-practices" src="http://blogs.sonatype.com/people/wp-content/uploads/2009/01/maven-ci-best-practices.png" alt="" width="115" height="94" />Continuous Integration is a development best practice that you need to be using in your process; it is an essential part of an efficient Software Development Lifecycle (SLDC).   If you aren&#8217;t using it already, then you should start, now.   The main benefit of Continuous Integration is the ability to flag errors as they are introduced into a system instead of waiting multiple days for test failures and critical errors to be identified during the QA cycle.  This post isn&#8217;t about the virtues of using CI, it&#8217;s about how to setup an optimal environment in a Maven shop.  Here are seven tips for running Maven builds in a CI system such as Hudson.<span id="more-1393"></span></p>

<p><strong>#1 Automate Snapshot Deployment</strong></p>

<p>In my experience, it is best to let your CI system deploy your snapshots. This is the most reliable way to guarantee that the contents of your repository are kept in sync with your source control system. In order to do this in a practical way, you need to couple CI with a repository manager like <a href="http://www.sonatype.com/products/nexus">Nexus</a> that can automatically purge snapshots. I&#8217;ve managed projects that produced &gt;300gb of snapshots in less than a week. Using a repository manager will save your sanity.</p>

<p><strong>#2 Isolate Local Repostitories</strong></p>

<p>Another critical component of a good CI setup is local repository isolation. The local repository in Maven is the temporary holding spot for all artifacts downloaded and produced by Maven, and it is not currently setup to be multi-process safe.   There is a remote possibility of a conflict, but it does exist.</p>

<p>The main reason I like to have a local repository per project is that it&#8217;s the only way to test that your project is build-able against the artifacts in the corporate repository. If you don&#8217;t have separate local repos, then the product on one build will be seen by another build on CI, even if it&#8217;s not in the corporate repository. This is important since one function of CI should be to validate that the code is buildable by a real developer.</p>

<p><em>Tip: use -Dmaven.repo.local=xxxx to define the unique local repositories for each build.</em></p>

<p><strong>#3 Regularly Purge Local Repositories</strong></p>

<p>To further validate the contents of the repository, and to manage the disk space, I purge the local repostories every night. This way if changes in the repository or artifacts are removed, the CI system will detect this. To keep it easy to purge all the local repositories, I tend to structure them under a single common folder such as /opt/repos/*.</p>

<p>Obviously having many local repositories requires more disk space than a single monolitic one due to dependency duplication, but even on our <a href="http://grid.sonatype.org/ci">large grid</a> the repos are less than 10gb total. Local repos get giant when you don&#8217;t control the snapshots and purging them nightly keeps this under control.</p>

<p><em>Tip: use your CI system itself to schedule the local repo cleanup. This way anyone can clean the repos manually right from the UI if Maven gets confused.</em></p>

<p><em>Over time, I&#8217;ve also picked up a few more simple tricks:</em></p>

<p><em><strong>#4 Enable Batch Mode</strong></em></p>

<p><em><em>Tip: Enable -B (batch) mode on the build.</em> This will make the logs shorter since it avoids the dependency download progress logging. It also ensures that the build won&#8217;t hang due to waiting for user input. </em><em>(to enable globally in settings.xml:&lt;interactiveMode&gt;false&lt;/interactiveMode&gt;)</em></p>

<p><em><strong>#5 Enable Full Stack Traces</strong></em></p>

<p><em><em>Tip: Enable -e to cause Maven to produce the full stack trace if there&#8217;s a build exception.</em> This will make it easier to comprehend any problems in the resulting build failure log/email without having to build it again.</em></p>

<p><em><strong>#6 Print Test Failures to Standard Output</strong></em></p>

<p><em><em>Tip: Enable -Dsurefire.useFile=false.</em> This is a favorite of mine since this causes surefire to print test failures to standard out, where it will get included in the build failure log and email. This saves you from having to dig back onto the machine to find the surefire report just to see a simple stack trace. (to enable globally in settings.xml:&lt;properties&gt;&lt;surefire.useFile&gt;true&lt;/surefire.useFile&gt;&lt;/properties&gt; in an active profile)</em></p>

<p><em><strong>#7 Always check for Snapshots</strong></em></p>

<p><em><em>Tip: Enable -U to cause Maven to always check for new snapshots.</em> (to enable globally in settings.xml: &lt;updatePolicy&gt;always&lt;/updatePolicy&gt;&#8230;.this goes on a repository definition) </em></p>

<p><em><strong>Summary</strong></em></p>

<p><em>Using the above settings and process causes every build to push the artifacts to the repository. The next downstream build will have its own clean repo and check the repository manager for the latest snapshots. Then at least once a day, everything is dumped locally and all dependencies are pulled out of the repository manager.</em></p>

<p><em>Naturally, doing all of this updating and purging puts some network load between the CI and repository manager. This works best if they share a highspeed network. If your repository manager isn&#8217;t close to your CI system, then you should put one there, if only to proxy the artifacts and reduce the impact of the daily local repo purge.</em></p>

<p><em><strong>Note: </strong>If you are going to follow these tips, it is essential that you download a copy of <a href="http://nexus.sonatype.org">Nexus</a>, purging the contents of your local repository and downloading everything from the Central Maven repository once a day (per project) is exactly the sort of behavior that causes traffic problems on the Central Maven repo.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven code: How to detect if you have a SNAPSHOT version</title>
		<link>http://blog.sonatype.com/people/2008/05/maven-code-how-to-detect-if-you-have-a-snapshot-version/</link>
		<comments>http://blog.sonatype.com/people/2008/05/maven-code-how-to-detect-if-you-have-a-snapshot-version/#comments</comments>
		<pubDate>Thu, 29 May 2008 16:13:17 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[snapshot]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/brian/?p=88</guid>
		<description><![CDATA[I answer this question often enough that I decided to burn it to a blog so I don&#8217;t have to dig it out of the source anymore&#8230;and maybe save someone else the time along the way. Here is the relevant code that Maven uses to determine if an artifact is a snapshot or not: String [...]]]></description>
				<content:encoded><![CDATA[<p>I answer this question often enough that I decided to burn it to a blog so I don&#8217;t have to dig it out of the source anymore&#8230;and maybe save someone else the time along the way.</p>

<p>Here is the relevant code that Maven uses to determine if an artifact is a snapshot or not:
<span id="more-618"></span></p>

<p style="font-size:small"></p>

<pre><span style="font-family: arial;">String LATEST_VERSION = "LATEST";
String SNAPSHOT_VERSION = "SNAPSHOT";
Pattern VERSION_FILE_PATTERN = Pattern.compile(
 "^(.*)-([0-9]{8}.[0-9]{6})-([0-9]+)$" );
public boolean isSnapshot()
{
     if ( version != null || baseVersion != null )
     {
       Matcher m = VERSION_FILE_PATTERN.matcher( getBaseVersion() );
       if ( m.matches() )
       {
          setBaseVersion( m.group( 1 ) + "-" + SNAPSHOT_VERSION );
          return true;
       }
       else
       {
         return getBaseVersion().endsWith( SNAPSHOT_VERSION ) ||
         getBaseVersion().equals( LATEST_VERSION );
       }
     }
     else
     {
       return false;
     }
  }
</span></pre>

<p>Essentially this regex ( regular expression ) is checking if the version ends with SNAPSHOT or if the pattern matches a timestamped version such as &#8220;2.0.10-20080415.233129-15&#8243;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2008/05/maven-code-how-to-detect-if-you-have-a-snapshot-version/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimal Maven Plugin configuration</title>
		<link>http://blog.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/</link>
		<comments>http://blog.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/#comments</comments>
		<pubDate>Tue, 27 May 2008 01:57:29 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/brian/?p=84</guid>
		<description><![CDATA[Maven has two sections in the pom relating to plugin configuration: project.build.plugins and project.build.pluginManagment.plugins. These two sections are unfortunately often confused and misused. PluginManagement is similar to dependencyManagment in that it provides configuration and defaults for plugins if they are used in the build. This is where we recommend you lock down your plugin versions, [...]]]></description>
				<content:encoded><![CDATA[<p>Maven has two sections in the pom relating to plugin configuration: <a href="http://maven.apache.org/pom.html#Plugins" target="_blank">project.build.plugins</a> and <a href="http://maven.apache.org/pom.html#Plugin_Management" target="_blank">project.build.pluginManagment.plugins</a>. These two sections are unfortunately often confused and misused.
<span id="more-616"></span>
PluginManagement is similar to <a href="http://maven.apache.org/pom.html#Dependency_Management" target="_blank">dependencyManagment </a>in that it provides configuration and defaults for plugins <em>if they are used in the build</em>. This is where we recommend you <a href="http://blogs.sonatype.com/brian/2008/04/10/1207873624557.html" target="_blank">lock down your plugin versions</a>, but it also allows default configuration.</p>

<p>The regular plugins section also allows the version and default configuration to be defined, and this is where the confusion lies. It is technically valid to define the plugin version and default configuration here, but I find it easier to grok the pom when following this guideline:</p>

<ul>
    <li>If the plugin block is not defining an execution (and thus binding maven to do something in the lifecycle), put that block in pluginManagment</li>
</ul>

<p>This means that configuration for plugins brought in by the default lifecycle such as resources, compiler, jar, etc will almost always go in the pluginManagement section. Doing so tends to keep your regular plugins section rather small and only showing the config for plugins that are doing <em>additional</em> things during the lifecycle.</p>

<p>Following the above defined guideline will also have you locating the config for plugins that are primarily run from the command line in pluginManagment&#8230;again keeping the plugins section clean and concise.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/feed/</wfw:commentRss>
		<slash:comments>171</slash:comments>
		</item>
		<item>
		<title>Adding additional source folders to your Maven build</title>
		<link>http://blog.sonatype.com/people/2008/05/adding-additional-source-folders-to-your-maven-build/</link>
		<comments>http://blog.sonatype.com/people/2008/05/adding-additional-source-folders-to-your-maven-build/#comments</comments>
		<pubDate>Fri, 23 May 2008 01:36:37 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/brian/?p=82</guid>
		<description><![CDATA[Occasionally you have a need to add additional source folders to your Maven build, usually when you are generating source via some external method or AntTask. Maven plugins that generate sources are expected to add the source folder automatically, but that&#8217;s of little consequence if your generation method is not supported by an existing Maven [...]]]></description>
				<content:encoded><![CDATA[<p>Occasionally you have a need to add additional source folders to your Maven build, usually when you are generating source via some external method or AntTask. Maven plugins that generate sources are expected to add the source folder automatically, but that&#8217;s of little consequence if your generation method is not supported by an existing Maven plugin. Fortunately, there is the <a href="http://mojo.codehaus.org/build-helper-maven-plugin/" target="_blank">build-helper-maven-plugin</a> to assist you. The usage page gives plenty of <a href="http://mojo.codehaus.org/build-helper-maven-plugin/usage.html" target="_blank">examples</a>. Adding an additional source folder is as simple as:
<span id="more-615"></span></p>

<pre>&lt;project&gt;
  ...
  &lt;build&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
        &lt;artifactId&gt;build-helper-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;1.1&lt;/version&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;id&gt;add-source&lt;/id&gt;
            &lt;phase&gt;generate-sources&lt;/phase&gt;
            &lt;goals&gt;
              &lt;goal&gt;add-source&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
              &lt;sources&gt;
                &lt;source&gt;some directory&lt;/source&gt;
                ...
              &lt;/sources&gt;
            &lt;/configuration&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;
&lt;/project&gt;</pre>

<p>Several threads cited from <a href="http://weblogs.java.net/blog/inder/archive/2008/05/teaching_maven2_1.html">Inderjeet&#8217;s blog</a> suggest tweaking the compiler plugin&#8217;s includes settings to add the additional source folder. While this will work in simple cases, this method does not actually add an additional sourceFolder element in the project model. This means other plugins, particularly IDE integrations such as <a href="http://m2eclipse.sonatype.org" target="_blank">M2eclipse </a>won&#8217;t see these folders and will cause you trouble down the road. We therefore suggest that you use the build-helper instead.</p>

<p>The build-helper lets you do some other handy things such as attach additional artifacts (<a href="http://blogs.sonatype.com/brian/2008/05/20/1211336408233.html">attachedArtifacts</a>), purge the project&#8217;s artifacts from the local repository and add additional testSource folders.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2008/05/adding-additional-source-folders-to-your-maven-build/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Misused Maven terms Defined</title>
		<link>http://blog.sonatype.com/people/2008/05/misused-maven-terms-defined/</link>
		<comments>http://blog.sonatype.com/people/2008/05/misused-maven-terms-defined/#comments</comments>
		<pubDate>Tue, 20 May 2008 01:15:47 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/brian/?p=80</guid>
		<description><![CDATA[When responding to questions on IRC, the Maven Users list, or giving Maven Training, I frequently run into misused terms of the Maven lingo. Here&#8217;s an attempt to define them &#8220;for the record&#8221;: Reactor When we refer to the &#8220;reactor&#8221; or &#8220;reactor build&#8221;, we are usually referring to the aggregation capability of Maven. If you [...]]]></description>
				<content:encoded><![CDATA[<p>When responding to questions on IRC, the Maven Users list, or giving <a href="http://www.sonatype.com/training">Maven Training</a>, I frequently run into misused terms of the Maven lingo. Here&#8217;s an attempt to define them &#8220;for the record&#8221;:
<span id="more-614"></span></p>

<h2>Reactor</h2>

<p>When we refer to the &#8220;reactor&#8221; or &#8220;reactor build&#8221;, we are usually referring to the aggregation capability of Maven. If you define a pom with &lt;modules&gt;, Maven will read all of these modules and build then in the correct order based on dependencies. The component that does this is also called the reactor, which is why the term is often applied to the action of aggregating the builds.</p>

<h2>Siblings</h2>

<p>Sibling poms are poms that are built inside the same reactor, and often share a common Parent pom.</p>

<h2>Parent Pom</h2>

<p>A parent pom is simply a pom from which other poms inherit via a &lt;parent&gt; section. Poms that inherit from a parent are sometimes referred to as &#8220;children&#8221; or &#8220;child poms.&#8221;</p>

<h2>Corporate Pom</h2>

<p>A Corporate Pom is a Parent Pom that sits at the top of an inheritance structure for a corporation. This is a recommended best practice for centralizing certain configuration such as <a href="http://maven.apache.org/plugins/maven-enforcer-plugin">Enforcer</a> rule configuration, default Plugin versions, etc. This may also be called an &#8220;Organizational Pom.&#8221; The term &#8220;Super Pom&#8221; is often mis-applied to Corporate Poms.</p>

<h2>Super Pom</h2>

<p>The Super Pom is a special pom that is contained inside the maven-project jar. This is the implied parent of all poms that don&#8217;t inherit from some other Parent pom. It is analogous to Java&#8217;s Object class. The Super Pom provides the defaults that make Maven easy to use, such as the Central repository, default locations for sources, etc. The Super Pom is not user editable but through the normal inheritance behavior of Maven, all the values may be overridden. To avoid confusion, the term Super Pom should be reserved for only this specific embedded pom.</p>

<h2>Artifact</h2>

<p>An artifact is essentially any file that is installed in a local repository or deployed to a remote <a href="http://nexus.sonatype.org">repository</a>. It has a unique id in the Maven coordinate system of groupId:artifactId:version:classifier:type.</p>

<h2>Dependency</h2>

<p>A dependency is an Artifact that is specifically declared in a pom to be needed for one of the various class path scopes.</p>

<h2>Attached Artifact</h2>

<p>Attached artifacts are additional related artifacts that get installed and deployed along with the &#8220;main&#8221; artifact. These are most often, javadocs, sources, bundles etc, but can actually be any file. A plugin must do the actual attaching, but random files may be attached with the <a href="http://mojo.codehaus.org/build-helper-maven-plugin/">build-helper-maven-plugin</a>.
Attached artifacts automatically share the same groupId, ArtifactId and version as the main artifact but they are distinguished with an additional Classifier field.</p>

<h2>Classifier</h2>

<p>The Classifier is the least known of the Maven coordinates. A primary artifact automatically has an empty classifier and is not changeable. All attached artifacts must differ from each other with unique classifiers. The Maven2 repository layout constructs file names in the following format: [groupId]-[artifactId]-[version]-[classifier].[type]. Common classifiers are: sources, javadocs, bin and bundle.</p>

<p>Our <a href="http://www.sonatype.com/book">book</a> shows all these elements and more in action.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2008/05/misused-maven-terms-defined/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to override a plugin&#039;s dependency in Maven</title>
		<link>http://blog.sonatype.com/people/2008/04/how-to-override-a-plugins-dependency-in-maven/</link>
		<comments>http://blog.sonatype.com/people/2008/04/how-to-override-a-plugins-dependency-in-maven/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 14:53:00 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[checkstyle]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://blogs.sonatype.com/people/brian/?p=72</guid>
		<description><![CDATA[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 [...]]]></description>
				<content:encoded><![CDATA[<p>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.</p>

<p>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.</p>

<p>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:
<span id="more-609"></span></p>

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

<p>This version of the <code>maven-checkstyle-plugin</code> 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:</p>

<pre>&lt;plugin&gt;
  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
  &lt;artifactId&gt;maven-checkstyle-plugin&lt;/artifactId&gt;
  &lt;version&gt;2.1&lt;/version&gt;
  &lt;executions&gt;
      &lt;execution&gt;
        &lt;id&gt;check my sources&lt;/id&gt;
        &lt;goals&gt;
          &lt;goal&gt;check&lt;/goal&gt;
        &lt;/goals&gt;
        &lt;phase&gt;compile&lt;/phase&gt;
      &lt;/execution&gt;
  &lt;/executions&gt;
<span style="color: red;">  &lt;dependencies&gt;
     &lt;dependency&gt;
        &lt;groupId&gt;checkstyle&lt;/groupId&gt;
        &lt;artifactId&gt;checkstyle&lt;/artifactId&gt;
        &lt;version&gt;4.4&lt;/version&gt;
     &lt;/dependency&gt;
  &lt;/dependencies&gt;</span>
&lt;/plugin&gt;</pre>

<p>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.</p>

<p>Now, what about reports? Well unfortunately, the Model used in 2.0.x doesn&#8217;t allow dependencies to be specified inside the reporting block (<a href="http://jira.codehaus.org/browse/MNG-1948">MNG-1948</a>)</p>

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

<p><strong>Update:</strong> 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&#8217;s what it looks like:</p>

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

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

<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;checkstyle version="4.4"&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2008/04/how-to-override-a-plugins-dependency-in-maven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
