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.

Customising Maven

Earlier in the User's Guide, you've seen how to configure a project.xml to build various different types of projects.

In addition to customising the build through the project model, additional properties can be set, and scripting can be used to define custom goals, or enhance the workflow during the build.

Extending the Build with Properties

There are two sets of properties: a small set of standard properties that are fundamental to the operation of Maven, and can be changed to customise for your particular environment or change the basic structure Maven uses for a project.

This properties reference above also explains the order in which properties files are loaded, and the reasons to use each.

The majority of properties in Maven are the plugin properties. These can be used to customise any aspect of the build process.

For example, if you are looking to change the way java sources are compiled, you can see the reference for the Java plugin properties. This allows you to set properties such as the -target setting, and whether to see deprecations. These can be added to project.properties for all builders of your project:

maven.compile.target=1.1
maven.compile.deprecation=on

While several of the most helpful properties are explained in the guides on this site, there is a full list of plugins available on the Plugins Reference mini-site. From there, you can navigate to the plugin you are interested in (which matches the first part of the goal name you are calling and wanting to configure), and on to its list of available properties.

Note that while properties are essential to configuring Maven and it's plugins, they can also be a source of bad practices. See the Best Practices guide for more information.

Property Substitution in the Project Descriptor

It is often much easier to parameterise values in the project descriptor (or in the properties files) with other properties or fields from the project descriptor than to redefine them each time. This is particularly powerful when used with inheritence, as seen in the next section.

For example, you might set the URL based on the artifact ID:

<project>
  <artifactId>my-project</artifactId>
  ...
  <url>http://www.mycompany.com/mainproject/subprojects/${pom.artifactId}</url>
</project>

For more information on how to specify expressions to use for interpolating these values, see the Jexl section of the Scripting Reference.

Project Inheritence

When working with multiple projects that share some information, it would be quite tedious to have to enter the same information into each project, or to maintain it afterwards.

For this reason, it is possible to extend a common project file:

<project>
  <extend>../project.xml</extend>
  ...
</project>

All elements are inherited and merged in, with later definitions overriding any defined earlier. Projects can be inherited to any level, but each can only extend one parent.

If there are any properties to be substituted into the parent POM or properties, the value will be evaluated after inheritence has been completed. For instance, if in the parent POM with artifact ID my-parent there was a description set like so:

<description>This is ${pom.artifactId}</description>

In the child project, if description were inherited and the artifact ID were my-child then the description would be This is my-child.

In addition to the project.xml definition, properties files and maven.xml files associated with the parent POM are inherited. Like the project descriptor properties and goals defined are added to those defined in the subprojects, with the subproject properties and goals overriding those from the parent if specified. preGoal and postGoal definitions that are inherited are accumulated though - all specified hooks will be executed.

Note: lists in the POM will overwrite lists defined in parent projects, with the exception of dependencies where the lists are accumulated.

Scripting Maven

If the provided plugins do not give all the flexibility needed to do the required tasks, you can add scripting to your project to go the last steps.

There are two ways to add additional goals and hooks to your project - through maven.xml, and by writing your own plugin. It is generally recommended to write your own plugin for any significant scripting effort as it will make it reusable across projects, separated, and allows you to use Java code as well as basic Jelly script.

The maven.xml file is tied to the project.xml file in the same directory, in the same way as project.properties is. This means that it is loaded and its goals processed whenever your project is, and also means that it is inherited from any projects you extend.

The format of maven.xml is typically like this:

<project default="jar:jar" xmlns:j="jelly:core">
 ...
</project>

The project element is the root element, and can specify a default goal name for the project. The namespace definitions are used by Jelly to import tag libraries.

Within this file, you can define new goals, or attach hooks to existing ones, write logic using Jelly tag libraries, and use existing Ant tasks to add build behaviour.

For more information on scripting in general, please see the Scripting reference. For particular information on building plugins, see Developing Plugins in this User's Guide.

As with properties, there are also some best practices to adhere to with regards to scripting Maven to ensure the build is maintainable.