Creating a Custom Lifecycle in Maven

Intro

 

Although it is not an everyday task, sometimes it is helpful to create a custom lifecycle in Maven.  For example, the jboss-maven-plugin unpack goal does not unpack (or explode) the WAR in the EAR.  It unpacks the EAR contents but it's not recursive.

 

In order to practice Agile development and boost your productivity in general, it is recommended to use as much hot incremental deployment (or hot redeployment) using JRebel or other tools (like Seam's special classloader to hot incrementally deploy changes to your JavaBeans, etc.)  If you're developing a Java EE project that results in a WAR or EAR+WAR(s), you'll notice that Maven executes the war:war goal when you run 'mvn clean install' command on your POM.

 

The following example will show you how to override that behavior and have Maven use the war:exploded goal instead.  For more info on the maven-war-plugin, see here: http://maven.apache.org/plugins/maven-war-plugin/plugin-info.html.

 

The Example

 

There are two XML descriptors that are required in addition to a custom plugin/Mojo to achieve our goal.

 

1) lifecycle.xml - specifies the lifecycle, phase and goal to be used when overriding the default lifecycle

2) components.xml - specifies the lifecycle mapping and phases that will be executed

3) A Mojo (Maven POJO) which extends AbstractMojo class and implements an execute() method.  The Mojo is the basis for our custom plugin.

 

So here's some code.

 

ExplodedMojo.java:

 

import org.apache.maven.plugin.AbstractMojo;import org.apache.maven.plugin.MojoExecutionException;
/** * @goal exploded * @execute lifecycle="explodedcycle"  phase="package" */public class ExplodedMojo extends AbstractMojo{   public void execute() throws MojoExecutionException  {     getLog().info( "doing nothing here" );  }}

 

 

 

pom.xml for maven-exploded-plugin:

 

 

<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>org.apache.maven.plugins</groupId>  <artifactId>maven-exploded-plugin</artifactId>  <packaging>maven-plugin</packaging>  <version>1.0-SNAPSHOT</version>  <name>maven-exploded-plugin Maven Mojo</name>  <url>http://maven.apache.org</url>  <dependencies>    <dependency>      <groupId>org.apache.maven</groupId>      <artifactId>maven-plugin-api</artifactId>      <version>2.0</version>    </dependency>  </dependencies></project>


 

 

pom.xml for our WAR project generated by 'mvn archetype:generate':

 





<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.intuit</groupId>
  <artifactId>testapp</artifactId>
  <!--<packaging>war</packaging>-->
  <packaging>exploded</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Maven Webapp Archetype</name>
  <url>http://maven.apache.org</url>  
  <build>
    <finalName>testapp</finalName>  
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-exploded-plugin</artifactId>
          <version>1.0-SNAPSHOT</version>
          <extensions>true</extensions>
        </plugin>    
      </plugins>
  </build>
</project>




 

 

 

 

 

 

components.xml

 





<component-set>
  <components>  
    <component>
          <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
          <role-hint>exploded</role-hint>
          <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
          <configuration>
                <phases>
                  <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
                  <compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
                  <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
                  <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
                  <test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
                  <package>org.apache.maven.plugins:maven-war-plugin:exploded</package>
                  <install>org.apache.maven.plugins:maven-install-plugin:install</install>
                  <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
                </phases>
          </configuration>
    </component>
  </components>
</component-set>




 

 

 

 

 

 

lifecycle.xml

 





<lifecycles>
  <lifecycle>
    <id>explodedcycle</id>
    <phases>
      <phase>
        <id>package</id>
        <executions>
          <execution>
            <goals>
              <goal>exploded</goal>
            </goals>
          </execution>
        </executions>
      </phase>
    </phases>
  </lifecycle>
</lifecycles>




 

 

 

 

 

 

Console output when running 'mvn clean package':

 





C:\Documents and Settings\asookazian\My Documents\ubuntu_projects.tar\projects\t
estapp>mvn clean package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Webapp Archetype
[INFO]    task-segment: [clean, package]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory C:\Documents and Settings\asookazian\My Documents\ubun
tu_projects.tar\projects\testapp\target
[INFO] Ignoring available plugin update: 2.5 as it requires Maven version 2.0.9
[INFO] [resources:resources]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] [compiler:compile]
[INFO] No sources to compile
[INFO] [resources:testResources]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Documents and Settings\asookazian\
My Documents\ubuntu_projects.tar\projects\testapp\src\test\resources
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [war:exploded]
[INFO] Exploding webapp
[INFO] Assembling webapp[testapp] in [C:\Documents and Settings\asookazian\My Do
cuments\ubuntu_projects.tar\projects\testapp\target\testapp]
[INFO] Processing war project
[INFO] Copying webapp resources[C:\Documents and Settings\asookazian\My Document
s\ubuntu_projects.tar\projects\testapp\src\main\webapp]
[INFO] Webapp assembled in [47 msecs]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Wed Jul 07 13:57:45 PDT 2010
[INFO] Final Memory: 9M/17M
[INFO] ------------------------------------------------------------------------





 

 

 

 

 

 

Note that war:exploded goal is executed, not war:war.  If you run 'mvn clean install', the build will fail because Maven has not created a packaged WAR to be installed to the local Maven repository.

 

References

 

Overriding the Default Lifecycle - http://www.sonatype.com/books/mvnref-book/reference/writing-plugins-sect-override-default-lifecycle.html

Creating a Customized Build Process in Maven - http://www.sonatype.com/people/2009/08/create-a-customized-build-process-in-maven/Note