Apache Maven 1.x has reached its end of life, and is no longer supported. For more information, see the announcement. Users are encouraged to migrate to the current version of Apache Maven.

Multiple Modules

Maven supports the notion of a product with multiple modules. While each project.xml is a discreet unit of work, they can be gathered together using the reactor to build simultaneously. The reactor was originally created to encourage the creation, or refactoring, of projects into smaller, discrete, more coherent units.

The reactor determines the correct build order from the dependencies stated by each project in their respective project descriptors, and will then execute a stated set of goals. It can be used for both building projects and other goals, such as site generation.

While the reactor requires you to write some Jelly script to interface with it, there is also a friendly wrapper plugin called multiproject that can allow you to control the setup with simple properties.

Using the Multiproject Plugin

Using the plugin is quite simple. The default set up assumes that you are in the top level directory of your build, and that and subdirectories that contain a project.xml file are subprojects to build.

To change this behaviour, set the maven.multiproject.includes and maven.multiproject.excludes properties appropriately, for example:

# Foo is broken, don't build it
maven.multiproject.excludes=foo/project.xml

All of the artifact based goals have a multiproject equivalent:

multiproject:install Build and install all projects into the local repository
multiproject:install-snapshot Build and install a timestamped build of all projects into the local repository
multiproject:deploy Build and install all projects, deploying to the remote repository
multiproject:deploy-snapshot Build and install a timestamped build of all projects, deploying to the remote repository

For the plugin to determine how to build each project, you must define a property for each project that requires it:

maven.multiproject.type=war

The default type is jar.

Note that the original purpose of the Multiproject plugin was to assist in aggregating the web site of subprojects, and so this comprises a large amount of the plugin's functionality. Simply by running:

maven multiproject:site

This goal will build the sites of all subprojects, including the top level that it was run from and will build an appropriate navigation to access each of the subprojects, and an overview listing the subprojects.

The behaviour of this goal and all others can be easily customised. For more information, see the Multiproject plugin reference.

Finally, you may wish to run some other goal(s) over the set of projects. To do this, run the following goal:

maven multiproject:goal -Dgoal=goal1,goal2

Using the Reactor

While the Multiproject plugin covers most common use cases in a convenient manner, in some instances it is necessary to access the reactor directly to execute multiple projects.

The normal use of the reactor tag is as follows:

<maven:reactor
  includes="**/project.xml"
  excludes=""
  banner="Building"
  goals="goal1, goal2"
  ignoreFailures="false"
/>

This will loop through every project.xml file found in the current tree, in the order defined by the dependencies they have on each other. The goals listed will be executed on each project in sequence.

The reactor tag is described in the Maven Jelly Tag Library reference.

Processing Projects after the Reactor

In some instances, you will want to work with the projects that the reactor did in your own script afterwards. To do this, you can utilise the ${reactorProjects} variable set in the Jelly context after each reactor execution. This is a list, and so can be iterated. Each variable in the list will be a project object, and can be used in the same way as ${pom} would normally be used.

If you'd like to gather a list of subprojects without executing any goals on them, this can be done by using the collectOnly attribute of the maven:reactor tag.

In some cases, you may wish to process a whole set of projects, and handle the failed projects differently. This requires that you set the ignoreFailures attribute to true in the maven:reactor tag. After all the projects have finished processing, the context variable ${failedProjects} will be available to iterate through and projects that failed to build completely.

If ignoreFailures is not set, it defaults to false and the entire build will end when one project fails to build.