Section 3.9. Creating Custom Top-Level Goals


3.9. Creating Custom Top-Level Goals

Now let's build the QOTD web application using our master project. Hold on! What does it mean to build the QOTD web application? Each subproject has its own definition of build: for the core subproject it means calling the jar:install goal, for the web subproject it means calling the war:install goal, etc. You need to define some common goals in your subprojects that you can call from your master project.

3.9.1. How do I do that?

You can do this easily, by creating a maven.xml file in each subproject and defining a custom goal in there. Let's call this goal qotd:build. Here's what you would put in the core/maven.xml file:

<?xml version="1.0"?>    <project default="qotd:build">   <goal name="qotd:build" prereqs="jar:install"/> </project>

The same applies for the other subprojects. For example, for the web subproject, you'll write:

<?xml version="1.0"?>    <project default="qotd:build">   <goal name="qotd:build" prereqs="war:install"/> </project>


Note: To manage different types of subproject builds, define the same custom goal in each subproject and use the Multiproject plug-in to execute it.

Now that each subproject has a qotd:build goal that builds it, you can also create a qotd:build goal in the master project's maven.xml file. This goal uses the Multiproject plug-in to call the qotd:build goal on all the subprojects:

<?xml version="1.0"?>    <project default="qotd:build"     xmlns:j="jelly:core">        <goal name="qotd:build">     <j:set var="goal" value="qotd:build"/>     <attainGoal name="multiproject:goal"/>   </goal>      <goal name="qotd:clean" prereqs="multiproject:clean,clean"/>    </project>


Tip: Maven 2 is multiproject-aware at its core, and calling a goal on a parent project will automatically call it on all the subprojects. In addition, it supports the notion of build lifecycle (compile, install, deploy, etc.) and plug-ins can bind goals to these different phases. As a consequence, there's no longer a need for custom top-level goals.

To build the full QOTD project, execute the qotd:build goal, and execute maven with no arguments, since the qotd:build goal is defined as the default goal in maven.xml:

C:\dev\mavenbook\code\qotd>maven [...] Starting the reactor... Our processing order: QOTD Core QOTD Web QOTD Acceptance Tests QOTD Packager +---------------------------------------- | Executing qotd:build QOTD Core | Memory: 3M/4M +---------------------------------------- [...] +---------------------------------------- | Executing qotd:build QOTD Web | Memory: 4M/7M +---------------------------------------- [...] +---------------------------------------- | Executing qotd:build QOTD Acceptance Tests | Memory: 5M/7M +---------------------------------------- [...] +---------------------------------------- | Executing qotd:build QOTD Packager | Memory: 6M/7M +---------------------------------------- [...] BUILD SUCCESSFUL Total time: 13 seconds

You may have noticed that the top-level maven.xml file also contains a useful qotd:clean goal. It directly uses one existing Multiproject plug-in goal called multiproject:clean. It also calls the clean goal because the master project is not in the multiproject includes list.

3.9.2. What about...

...using the existing multiproject:install goal to automatically build all subprojects and install their artifacts?

This is indeed a possibility. In order to use it you would need to define each subproject's type using the maven.multiproject.type property. Some valid types are jar (the default), war, ear, and plugin. When you call multiproject:install, the Multiproject plug-in calls the ${maven.multiproject.type}:install goal for each subproject. This means you could possibly define custom project types and provide a corresponding custom goal in your project's maven.xml file. In the QOTD case, the acceptance subproject does not generate any artifact, so you would have needed to define a qotd:install goal that simply ran the acceptance tests. As the packager subproject also contains custom build logic to generate the zip file artifact, you would also have needed to define a qotd:install goal that creates the zip file.

All in all it's sometimes better to create your own qotd:build goals, for the following reasons:

  • The qotd:build goals tell your build users what goals they are supposed to be running. As you know, Maven provides hundreds of available goals, and without these custom goals new users might get a bit lost as to what goal they should execute to build your project.

  • The multiproject:install goal is nice if you only have projects that generate artifacts. But in practice, projects do all sort of things when they are built, and producing artifacts is only one aspect of the build.

However, don't overdo it! Remember that Maven is here so that you don't have to maintain a build code. Try reusing existing plug-in goals as much as possible.


Note: Always try to minimize the size of your maven.xml files.


Maven. A Developer's Notebook
Maven: A Developers Notebook (Developers Notebooks)
ISBN: 0596007507
EAN: 2147483647
Year: 2003
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net