<?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; lifecycle</title>
	<atom:link href="http://www.sonatype.com/people/tag/lifecycle/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.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, 09 Feb 2012 15:48:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Create a Customized Build Process in Maven</title>
		<link>http://www.sonatype.com/people/2009/08/create-a-customized-build-process-in-maven/</link>
		<comments>http://www.sonatype.com/people/2009/08/create-a-customized-build-process-in-maven/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 17:54:51 +0000</pubDate>
		<dc:creator>John Casey</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[advanced maven]]></category>
		<category><![CDATA[lifecycle]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=2658</guid>
		<description><![CDATA[Creating a custom Maven lifecycle mapping for your project's build process isn't that difficult, as long as you know a couple of tricks.]]></description>
			<content:encoded><![CDATA[<p>Maven&#8217;s build process is driven by three key concepts: the build lifecycle, mojos, and the lifecycle mappings. If you&#8217;re not familiar with these concepts, you can read up on them in <a href="http://sonatype.com/products/maven/documentation/book-defguide">Maven, The Definitive Guide</a>, especially <a href="http://www.sonatype.com/books/maven-book/reference/introduction.html">Chapter 1</a> and <a href="http://www.sonatype.com/books/maven-book/reference/lifecycle.html">Chapter 10</a>.</p>

<p>Maven&#8217;s basic unit of work during the build is the Mojo (Maven POJO). Mojos are contained in plugins that group them together with similar functions. Additionally, Maven supplies a standard set of scaffolds &#8211; called <em>build lifecycles</em> &#8211; that provide an abstract, structured progression of the types of activities (<em>lifecycle phases</em>) typically found in a build. The standard build for a particular type of project is defined when the appropriate mojos are bound to the appropriate lifecycle phases using a <em>lifecycle mapping</em>.</p>

<p>Obviously, this is only a starting point; individual projects can further fine-tune their own builds by binding or reconfiguring mojos in their own POMs. However, the default build for a particular type of project &#8211; specified by the <em>packaging</em> element in the POM &#8211; is defined by its lifecycle mapping.</p>

<p>Maven provides mappings for many common project packagings out-of-the-box. But what if we have a custom project type? Maybe something that produces a particular type of artifact that only our internal systems know how to use? If we&#8217;re building a large number of these projects, it may make sense to teach Maven to support a custom project packaging. This is a relatively easy task, if you know a few tricks.</p>

<h2 id="the_custom_lifecyle_mapping">The Custom Lifecyle Mapping</h2>

<p>In many cases, we&#8217;re interested in building a project artifact that is loosely based on the <code>jar</code> archive layout, with some critical details such as files added to <code>META-INF/</code> that turn it into more than a run-of-the-mill classpath entry.</p>

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

<p>To create a lifecycle mapping for this sort of packaging, we&#8217;re really interested in creating something that&#8217;s basically a <em>jar++</em> mapping. In our case, we&#8217;re going to define a new packaging type for plugins of a mythical app, called &#8216;WeatherMaker&#8217;. We&#8217;ll call the packaging <code>wm-plugin</code>.</p>

<p>As the foundation for the <code>wm-plugin</code> lifecycle mapping, we&#8217;ll start by copying the standard <code>jar</code> lifecycle mapping component from the <code>components.xml</code> file in <a href="http://svn.apache.org/repos/asf/maven/maven-2/tags/maven-2.2.0/maven-core/src/main/resources/META-INF/plexus/components.xml">Maven SVN</a> (<strong>NOTE:</strong> This is a fairly large file, so you might want to search for <code>role-hint&gt;jar</code>). The <code>jar</code> lifecycle-mapping component definition looks like this:</p>

<pre><code>    &lt;component&gt;
      &lt;role&gt;org.apache.maven.lifecycle.mapping.LifecycleMapping&lt;/role&gt;
      &lt;role-hint&gt;jar&lt;/role-hint&gt;
      &lt;implementation&gt;
        org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
      &lt;/implementation&gt;
      &lt;configuration&gt;
        &lt;lifecycles&gt;
          &lt;lifecycle&gt;
            &lt;id&gt;default&lt;/id&gt;
            &lt;phases&gt;
              &lt;process-resources&gt;
                org.apache.maven.plugins:maven-resources-plugin:resources
              &lt;/process-resources&gt;
              &lt;compile&gt;
                org.apache.maven.plugins:maven-compiler-plugin:compile
              &lt;/compile&gt;
              &lt;process-test-resources&gt;
                org.apache.maven.plugins:maven-resources-plugin:testResources
              &lt;/process-test-resources&gt;
              &lt;test-compile&gt;
                org.apache.maven.plugins:maven-compiler-plugin:testCompile
              &lt;/test-compile&gt;
              &lt;test&gt;
                org.apache.maven.plugins:maven-surefire-plugin:test
              &lt;/test&gt;
              &lt;package&gt;
                org.apache.maven.plugins:maven-jar-plugin:jar
              &lt;/package&gt;
              &lt;install&gt;
                org.apache.maven.plugins:maven-install-plugin:install
              &lt;/install&gt;
              &lt;deploy&gt;
                org.apache.maven.plugins:maven-deploy-plugin:deploy
              &lt;/deploy&gt;
            &lt;/phases&gt;
          &lt;/lifecycle&gt;
        &lt;/lifecycles&gt;
      &lt;/configuration&gt;
    &lt;/component&gt;
</code></pre>

<p>You&#8217;ll notice that this lifecycle mapping only addresses the <code>default</code> lifecycle, but not the <code>clean</code> or <code>site</code> lifecycles. Since Maven&#8217;s default mapping for these two lifecycles is sufficient for most use cases, most lifecycle mapping components don&#8217;t need to define them explicitly.</p>

<p>Basically, the lifecycle mapping above lists the phases to which particular mojo bindings are made, and each mojo binding within a phase is listed in terms of its plugin coordinate &#8211; the <code>groupId</code>, <code>artifactId</code>, and optionally, <code>version</code> of the plugin &#8211; along with the mojo&#8217;s own name, or <code>goal</code>. The format for each mojo binding is: <code>$groupId:$artifactId:[$version:]$goal</code>. If the version is omitted, Maven will search the POM&#8217;s <code>plugins</code> and <code>pluginManagement</code> sections, and ultimately default over to the latest released version of the plugin if no other version specification can be found.</p>

<p>To build on the standard <code>jar</code> format, we&#8217;re going to be using a mojo called <code>generate-descriptor</code> from a plugin called <code>weathermaker-maven-plugin</code> with a groupId of <code>org.sonatype.example.plugins</code> to generate a plugin descriptor file for inclusion in the project artifact. Since this descriptor is generated, and is a classpath resource (not something to be compiled), it should be bound to the <code>generate-resources</code> lifecycle phase.</p>

<p>Our modified lifecycle mapping looks like this:</p>

<pre><code>    &lt;component&gt;
      &lt;role&gt;org.apache.maven.lifecycle.mapping.LifecycleMapping&lt;/role&gt;
      &lt;!-- The POM packaging for this type of project is 'wm-plugin' --&gt;
      &lt;role-hint&gt;wm-plugin&lt;/role-hint&gt;
      &lt;implementation&gt;
        org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
      &lt;/implementation&gt;
      &lt;configuration&gt;
        &lt;lifecycles&gt;
          &lt;lifecycle&gt;
            &lt;id&gt;default&lt;/id&gt;
            &lt;phases&gt;
              &lt;!-- Generate the plugin descriptor marking this artifact
                         as a plugin for the weathermaker application. --&gt;
              &lt;generate-resources&gt;
                org.sonatype.example.plugins:weathermaker-maven-plugin:\
                  ${project.version}:generate-descriptor
              &lt;/generate-resources&gt;
              &lt;process-resources&gt;
                org.apache.maven.plugins:maven-resources-plugin:resources
              &lt;/process-resources&gt;
              &lt;compile&gt;
                org.apache.maven.plugins:maven-compiler-plugin:compile
              &lt;/compile&gt;
              &lt;process-test-resources&gt;
                org.apache.maven.plugins:maven-resources-plugin:testResources
              &lt;/process-test-resources&gt;
              &lt;test-compile&gt;
                org.apache.maven.plugins:maven-compiler-plugin:testCompile
              &lt;/test-compile&gt;
              &lt;test&gt;
                org.apache.maven.plugins:maven-surefire-plugin:test
              &lt;/test&gt;
              &lt;package&gt;
                org.apache.maven.plugins:maven-jar-plugin:jar
              &lt;/package&gt;
              &lt;install&gt;
                org.apache.maven.plugins:maven-install-plugin:install
              &lt;/install&gt;
              &lt;deploy&gt;
                org.apache.maven.plugins:maven-deploy-plugin:deploy
              &lt;/deploy&gt;
            &lt;/phases&gt;
          &lt;/lifecycle&gt;
        &lt;/lifecycles&gt;
      &lt;/configuration&gt;
    &lt;/component&gt;
</code></pre>

<p><strong>NOTE:</strong> The backslash (&#8216;\&#8217;) above indicates a continued line. This is very important!</p>

<p>We&#8217;ve made two important changes in the lifecycle mapping above: we changed the role-hint to match the new POM packaging, and we added the mojo binding to generate a weathermaker plugin descriptor. Again, the POM <code>packaging</code> element is keyed to this change:</p>

<pre><code>    &lt;!-- The POM packaging for this type of project is 'wm-plugin' --&gt;
    &lt;role-hint&gt;wm-plugin&lt;/role-hint&gt;
</code></pre>

<p>The customized mojo binding is added to the <code>generate-resources</code> lifecycle phase like this:</p>

<pre><code>&lt;!-- Generate the plugin descriptor marking this artifact
as a plugin for the weathermaker application. --&gt;
&lt;generate-resources&gt;
  org.sonatype.example.plugins:weathermaker-maven-plugin:\
    ${project.version}:generate-descriptor
&lt;/generate-resources&gt;
</code></pre>

<p><em>(Watch that backslash! It indicates a continued line!)</em></p>

<p>Also, notice the use of the expression <code>${project.version}</code> in our custom lifecycle binding. This isn&#8217;t critical for now, but if we&#8217;re releasing the custom lifecycle mapping as part of the weathermaker application, as part of a developer pack with the <code>weathermaker-maven-plugin</code>, it might make sense to key the lifecycle in to the particular version of the plugin with which it was released. At build time for this lifecycle mapping project (not projects that use the mapping), we&#8217;ll filter a concrete value into the component definition in place of this expression, allowing it to stay up to date with successive application releases.</p>

<p>Of course, we could choose to add or subtract any number of mojo bindings to our custom lifecycle mapping. However, since the jar build process is fairly well-understood, it&#8217;s generally good practice to change as little as possible to avoid unwanted side effects. At this point, we can include this new component in a <code>components.xml</code> file, wrapped in the following XML:</p>

<pre><code>    &lt;?xml version="1.0"?&gt;
    &lt;component-set&gt;
      &lt;components&gt;
        &lt;!-- lifecycle mapping component goes here --&gt;
      &lt;/components&gt;
    &lt;/component-set&gt;
</code></pre>

<h2 id="packaging_the_lifecycle_mapping">Packaging The Lifecycle Mapping</h2>

<p>Now, we can include this in a skeletal Maven project, inside the standard resources directory structure:</p>

<pre><code>    |- weathermaker-plugin-lifecycle/
    |  |- pom.xml
    |  |- src/
    |  |  |- main/
    |  |  |  |- resources/
    |  |  |  |  |- META-INF/
    |  |  |  |  |  |- plexus/
    |  |  |  |  |  |  |- components.xml
</code></pre>

<p>&#8230;and add a basic POM:</p>

<pre><code>    &lt;?xml version="1.0"?&gt;
    &lt;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/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
      &lt;parent&gt;
        &lt;groupId&gt;org.sonatype.examples.weathermaker&lt;/groupId&gt;
        &lt;artifactId&gt;weathermaker-parent&lt;/artifactId&gt;
        &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
      &lt;/parent&gt;
      &lt;artifactId&gt;weathermaker-plugin-lifecycle&lt;/artifactId&gt;
      &lt;build&gt;
        &lt;resources&gt;
          &lt;resource&gt;
            &lt;directory&gt;src/main/resources&lt;/directory&gt;
            &lt;filtering&gt;true&lt;/filtering&gt;
          &lt;/resource&gt;
        &lt;/resources&gt;
      &lt;/build&gt;
    &lt;/project&gt;
</code></pre>

<p><em>(Again, backslashes indicate line continuations.)</em></p>

<p>Note that this isn&#8217;t <em>quite</em> your run-of-the-mill POM. We&#8217;re redefining the default resources directory to be filtered, so the weathermaker project version will be filtered into the lifecycle-mapping component, and tie our custom mojo bindings to a particular version of the weathermaker-maven-plugin.</p>

<p>Once we build this project, we&#8217;ll have a jar artifact that we can reference as a build extension in our project POMs, so we can use the new lifecycle mapping.</p>

<p>It may look like our job it finished, but we&#8217;re not quite finished yet. Read on!</p>

<h2 id="additional_details_the_artifacthandler_component">Additional Details: The ArtifactHandler Component</h2>

<p>As long as we&#8217;re fine with having our new weathermaker plugin artifacts deployed into the maven repository with the extension <code>.wm-plugin</code>, and we&#8217;re not concerned with having these plugin artifacts added to the classpath when they&#8217;re specified as dependencies in other projects, we&#8217;re basically done. However, since we&#8217;re interested in creating weathermaker plugins that depend on other weathermaker plugins (even if they&#8217;re expected to be provided by the core weathermaker application), this isn&#8217;t a great solution for us. Additionally, since wm-plugin artifacts are really just jars with some additional special sauce, it might be a lot less confusing to name them with the standard <code>.jar</code> extension.</p>

<p>To achieve these goals, we need to define a custom <code>ArtifactHandler</code> component to accompany our new lifecycle mapping. Artifact handlers provide Maven with some basic handling instructions for artifacts (and dependencies) that match a particular <em>type</em>.</p>

<p>The handler component may map the given type to a different extension; specify that it is self-contained and includes its own dependencies; define the language in which the artifact is implemented; or tell Maven whether the artifact is intended to be used as part of a classpath, maybe for use in compiling the current project&#8217;s source code. Fortunately, the <code>ArtifactHandler</code> component definition is simple and straightforward.</p>

<p>Again, we can base the handler for our <code>wm-plugin</code> artifacts on a pre-existing handler. However, this time we&#8217;ll use the <code>ArtifactHandler</code> for <code>ejb</code> artifacts as our starting point (from <a href="http://svn.apache.org/repos/asf/maven/maven-2/tags/maven-2.2.0/maven-artifact/src/main/resources/META-INF/plexus/components.xml">Maven SVN</a>):</p>

<pre><code>    &lt;component&gt;
      &lt;role&gt;org.apache.maven.artifact.handler.ArtifactHandler&lt;/role&gt;
      &lt;role-hint&gt;ejb&lt;/role-hint&gt;
      &lt;implementation&gt;
        org.apache.maven.artifact.handler.DefaultArtifactHandler
      &lt;/implementation&gt;
      &lt;configuration&gt;
        &lt;type&gt;ejb&lt;/type&gt;
        &lt;extension&gt;jar&lt;/extension&gt;
        &lt;language&gt;java&lt;/language&gt;
        &lt;addedToClasspath&gt;true&lt;/addedToClasspath&gt;
      &lt;/configuration&gt;
    &lt;/component&gt;
</code></pre>

<p>Just as with the lifecycle mapping, this component&#8217;s <code>role-hint</code> element maps it to the POM <code>packaging</code> element. Additionally, the same <code>role-hint</code> element also maps the handler to the <code>type</code> element used when specifying a <code>dependency</code> in the POM. As you can see, there is a redundant <code>type</code> element in the configuration for this component; this element may be vestigial, but we&#8217;ll specify it correctly just to be safe:</p>

<pre><code>    &lt;component&gt;
      &lt;role&gt;org.apache.maven.artifact.handler.ArtifactHandler&lt;/role&gt;
      &lt;!-- We want to look this up by dependency-type
                 and POM packaging 'wm-plugin' --&gt;
      &lt;role-hint&gt;wm-plugin&lt;/role-hint&gt;
      &lt;implementation&gt;
        org.apache.maven.artifact.handler.DefaultArtifactHandler
      &lt;/implementation&gt;
      &lt;configuration&gt;
        &lt;!-- This should always be consistent with the role-hint,
                    to be safe. --&gt;
        &lt;type&gt;wm-plugin&lt;/type&gt;
        &lt;extension&gt;jar&lt;/extension&gt;
        &lt;language&gt;java&lt;/language&gt;
        &lt;addedToClasspath&gt;true&lt;/addedToClasspath&gt;
      &lt;/configuration&gt;
    &lt;/component&gt;
</code></pre>

<p>As you can see, the <code>extension</code> is left with the standard value, <code>jar</code>. Aside from this, we&#8217;re telling Maven that artifacts of this type are implemented in Java, and are meant to participate in classpaths.</p>

<p>Again, our customizations basically center on the role-hint:</p>

<pre><code>&lt;!-- We want to look this up by dependency-type
       and POM packaging 'wm-plugin' --&gt;
&lt;role-hint&gt;wm-plugin&lt;/role-hint&gt;
</code></pre>

<p>However, we change the <code>type</code> element to maintain consistency:</p>

<pre><code>&lt;!-- This should always be consistent with the role-hint,
        to be safe. --&gt;
&lt;type&gt;wm-plugin&lt;/type&gt;
</code></pre>

<p>Now, we simply add our new <code>ArtifactHandler</code> component definition to the same <code>src/main/resources/META-INF/plexus/components.xml</code> file that houses our custom lifecycle mapping. At this point, we <strong>should</strong> be able to rebuild the <code>weathermaker-plugin-lifecycle</code> project and be able to install, deploy, and resolve weathermaker-plugin artifacts using the filename extension <code>.jar</code>. <strong>However</strong>, due to a couple known bugs in Maven versions prior to 2.2.1 (which is quickly nearing release), our new artifact handler will not quite work as expected for the install and deploy steps. To make that part work, we need to work around the bugs.</p>

<h2 id="working_around_known_issues">Working Around Known Issues</h2>

<p>The most difficult and persistent problems in Maven mostly arise from timing issues, or what&#8217;s commonly referred to as chicken-and-egg scenarios. In this particular case, we need to understand a little about how Maven works internally in order to understand why project builds don&#8217;t use our new ArtifactHandler.</p>

<p>Maven builds project instances before it does almost anything else. It does so by collapsing the inheritance hierarchy of a particular POM, performing steps like expression resolution and some other intermediate processing, then initializing the project&#8217;s main artifact.</p>

<p>Only after Maven has created project instances for each POM in the current build will it load any build extensions that are specified, and start executing the build lifecycle itself. The reason extension loading takes place so late in the process is because all configuration in Maven hinges on the project instance.</p>

<p>Any properties specified in profiles within the <code>settings.xml</code> file are injected into project instances; likewise, build extensions and plugins that are treated as build extensions are specified in the POM. Since these plugin specifications may need additional information from ancestral POMs, they cannot be loaded safely until the project instance is fully calculated.</p>

<p>What does this mean for us? Remember where the project artifact is constructed; when this happens, Maven uses all available ArtifactHandler definitions, and creates ArtifactHandler instances for any POM <code>packaging</code> or dependency <code>type</code> it encounters that doesn&#8217;t already have a handler defined. As I mentioned above, the whole point of our custom ArtifactHandler was to escape the vagaries of these on-the-fly ArtifactHandlers. Since our custom ArtifactHandler isn&#8217;t available when the project artifact is created, it&#8217;s not used, and the project uses the on-the-fly version to install or deploy the project&#8217;s build output.</p>

<p>To work around this shortcoming, we need to inject some custom behavior that executes at the beginning of the build, before the build has really done anything. This custom behavior will forcibly lookup all ArtifactHandler components that &#8211; for whatever reason &#8211; haven&#8217;t been connected to the ArtifactHandlerManager component that Maven uses when resolving artifacts. It will also attempt to reset the ArtifactHandler instance used by the project artifact, forcing Maven to use our custom ArtifactHandler. The simplest way to inject this sort of code is by creating a custom Mojo and binding it to the <code>initialize</code> phase of the default build lifecycle.</p>

<p>The resulting mojo code is too long to list here, but you can see an example in the <a href="http://svn.sonatype.org/plugins/trunk/app-lifecycle/app-lifecycle-maven-plugin/src/main/java/org/sonatype/maven/plugin/app/buildhelper/InjectArtifactHandlerMojo.java">app-lifecycle-maven-plugin</a>, which is used to build plugins for Sonatype applications such as <a href="http://nexus.sonatype.org/">Nexus</a>.</p>

<p>Once we have the mojo, we still need to add it to our lifecycle mapping:</p>

<pre><code>    &lt;component&gt;
      &lt;role&gt;org.apache.maven.lifecycle.mapping.LifecycleMapping&lt;/role&gt;
      &lt;role-hint&gt;wm-plugin&lt;/role-hint&gt;
      &lt;implementation&gt;
        org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
      &lt;/implementation&gt;
      &lt;configuration&gt;
        &lt;lifecycles&gt;
          &lt;lifecycle&gt;
            &lt;id&gt;default&lt;/id&gt;
            &lt;phases&gt;
              &lt;!-- Inject our custom ArtifactHandler into the project's main artifact,
                         and fixup any dependency artifacts that may be wrong. --&gt;
              &lt;initialize&gt;
                org.sonatype.example.plugins:weathermaker-maven-plugin:\
                  ${project.version}:inject-artifact-handler
              &lt;/initialize&gt;
              ...
</code></pre>

<p><em>(Once again, remember that the backslash above denotes a line continuation.)</em></p>

<p>At this point, we&#8217;ve defined a custom lifecycle mapping to define the set of mojos that take part in building our custom weathermaker plugins, along with configuring where in the build they execute. We&#8217;ve defined a custom ArtifactHandler component to tell Maven that even though the POM <code>packaging</code> and dependency <code>type</code> elements say <code>wm-plugin</code>, it should actually be dealing with files that have an extension of <code>.jar</code>.</p>

<p>Finally, we&#8217;ve added a custom mojo to work around some known bugs in Maven that prevent project artifacts from taking advantage of custom ArtifactHandler components. Technically, we&#8217;re done. We can rebuild the <code>weathermaker-maven-plugin</code> and <code>weathermaker-plugin-lifecycle</code> projects, configure our projects to use them, and we&#8217;re ready to go.</p>

<p>But we could still streamline this a bit more to make it easier to use.</p>

<h2 id="packaging_revisited">Packaging Revisited</h2>

<p>Right now, we have two custom artifacts that must be available to build our weathermaker plugins: one jar filled with mapping component definitions, and a plugin artifact which the mapping artifact references. Both of these artifacts have to be present for the build to work, and they will never be used separately.</p>

<p>So, why not combine them?</p>

<p>As you may have noticed if you read closely, there are two ways to define custom extensions in Maven: the <code>extensions</code> section, and using the <code>extensions</code> flag inside of a <code>plugin</code> definition. Up to this point, we&#8217;ve sort of assumed that we&#8217;d be using the <code>extensions</code> section of the POM, located directly inside the <code>build</code> section. This is the purest approach, in the sense that it&#8217;s the natural choice if your artifact provides only lifecycle mappings, artifact handlers, and the like.</p>

<p>However, if your lifecycle mapping references a plugin that must be present for the lifecycle to run, then it makes a lot more sense to include that lifecycle mapping inside the plugin itself, and use the <code>extensions</code> == <code>true</code> flag in your POM&#8217;s plugin configuration itself. This makes the plugin much more self-contained, and reduces the risk of one or the other artifact going missing for some reason (e.g. a network outage).</p>

<p>To include our mapping components inside the weathermaker-maven-plugin, we simply copy the resources directory over to the plugin&#8217;s directory structure and update the plugin POM to filter those resources:</p>

<pre><code>    &lt;build&gt;
      &lt;resources&gt;
        &lt;resource&gt;
          &lt;directory&gt;src/main/resources&lt;/directory&gt;
          &lt;filtering&gt;true&lt;/filtering&gt;
        &lt;/resource&gt;
      &lt;/resources&gt;
    &lt;/build&gt;
</code></pre>

<p>Once we&#8217;ve copied the resources and added the above POM configuration, we can scrap the weathermaker-plugin-lifecycle project altogether, and start using the weathermaker-maven-plugin exclusively.</p>

<h2 id="configuring_your_project_pom">Configuring Your Project POM</h2>

<p>Yes, but&#8230;how exactly do we do that?</p>

<p>In the POM for our weathermaker plugin project, we simply add the following plugin configuration:</p>

<pre><code>    &lt;build&gt;
      &lt;plugins&gt;
        &lt;plugin&gt;
          &lt;groupId&gt;org.sonatype.example.plugins&lt;/groupId&gt;
          &lt;artifactId&gt;weathermaker-maven-plugin&lt;/artifactId&gt;
          &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
          &lt;!-- This is the magic configuration! --&gt;
          &lt;extensions&gt;true&lt;/extensions&gt;
        &lt;/plugin&gt;
      &lt;/plugins&gt;
    &lt;/build&gt;
</code></pre>

<p>Inclusion of this plugin with the <code>extensions</code> flag set to <code>true</code> will cause Maven to load our custom lifecycle-mapping and artifact-handler components and use them to execute our customized build process for the project.</p>

<p>Congratulations! You&#8217;re done.</p>

<h2 id="resources">Resources</h2>

<ul>
    <li><a href="http://sonatype.com/products/maven/documentation/book-defguide">Maven, The Definitive Guide</a>
<ul>
    <li><a href="http://www.sonatype.com/books/maven-book/reference/introduction.html">Chapter 1, Introducing Apache Maven</a></li>
    <li><a href="http://www.sonatype.com/books/maven-book/reference/lifecycle.html">Chapter 10, The Build Lifecycle</a></li>
</ul>
</li>
    <li><code>maven-core</code> <a href="http://svn.apache.org/repos/asf/maven/maven-2/tags/maven-2.2.0/maven-core/src/main/resources/META-INF/plexus/components.xml">components.xml</a>, from Maven 2.2.0 SVN (including the <code>jar</code> lifecycle mapping)</li>
    <li><code>maven-artifact</code> <a href="http://svn.apache.org/repos/asf/maven/maven-2/tags/maven-2.2.0/maven-artifact/src/main/resources/META-INF/plexus/components.xml">components.xml</a>, from Maven 2.2.0 SVN (including the <code>ejb</code> ArtifactHandler)</li>
    <li><a href="http://svn.sonatype.org/plugins/trunk/app-lifecycle/app-lifecycle-maven-plugin/src/main/java/org/sonatype/maven/plugin/app/buildhelper/InjectArtifactHandlerMojo.java">inject-artifact-handlers mojo</a>, from the <code>app-lifecycle-maven-plugin</code>, used to build <a href="http://nexus.sonatype.org/">Nexus</a> plugins</li>
</ul>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2009/08/create-a-customized-build-process-in-maven/&via=SonatypeCM&text=Create a Customized Build Process in Maven&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2009/08/create-a-customized-build-process-in-maven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

