Section 3.2. Using POM Inheritance


3.2. Using POM Inheritance

Maven projects are completely described by a Project Object Model (POM), and when you break a project into subprojects, each subproject will have its own POM. Because a series of related projects most likely originated from the same organization, have the same developer team, and use a similar set of dependencies, related project POMs will tend to contain duplicate data. From the previous example, core would contain the same developers element as web, which would contain the same developers element as the packager project. Configuration duplication is just as bad as code duplication, and to reduce the amount of work to maintain related POMs you'll need to have each POM inherit from a super-POM. When a project's POM inherits from a common POM, subprojects need to specify only how they're different from the main project. Maven supports project inheritance, which means that any subproject can inherit from its parent's project.xml, maven.xml, and properties files (project.properties and build.properties).

3.2.1. How do I do that?

Figure 3-2 shows the four subprojects' project.xml files, along with a new common/ directory that you have created. The common/ directory contains the shared project.xml and project.properties files you want all subprojects to inherit from. You can put in the common/ directory any Maven build-related file you wish to share between your Maven subprojects; this includes project.properties, project.xml, and maven.xml.

Figure 3-2. Maven build files inheriting from common definitions


Take a look at the common/project.xml file:

<?xml version="1.0"?> <project>   <pomVersion>3</pomVersion>   <groupId>mdn</groupId>   <currentVersion>1.0</currentVersion>   <organization>     <name>O'Reilly</name>     <url>http://www.oreilly.com/</url>     <logo>http://www.oreilly.com/images/oreilly/oreilly_header1.gif</logo>   </organization>   <inceptionYear>2005</inceptionYear>      <url>     http://www.mavenbook.org/projects/${pom.groupId}/${pom.artifactId}   </url>      <siteAddress>www.mavenbook.org</siteAddress>   <siteDirectory>     /var/www/html/mavenbook/projects/${pom.groupId}/${pom.artifactId}   </siteDirectory>        <mailingLists/>      <developers>     [...]   </developers>    </project>

All those XML tags are going to be common for all other subprojects. Every project is going to have the same organization, the same inception year, and the same URL format. The project's URL is constructed using references to the ${pom} variable, as introduced in Section 2.1. When Maven evaluates the url or the siteDirectory for a subproject, it will use the POM values specific to that subproject. To see how a project would inherit the values defined in common/project.xml, take a look at core/project.xml:


Note: You achieve inheritance by using the extend element in a project's project.xml file.
<?xml version="1.0"?> <project>   <extend>../common/project.xml</extend>   <name>QOTD Core</name>   <artifactId>qotd-core</artifactId>   <package>mdn.qotd.core</package>   <shortDescription>QOTD core library</shortDescription>


Note: Most elements in the parent POM are overridden by the child's POM elements. However, the dependencies elements are additive (i.e., these elements will be aggregated).
  <description>     QOTD core library   </description>     <dependencies>     <dependency>       <groupId>rome</groupId>       <artifactId>rome</artifactId>       <version>0.5</version>     </dependency>     <dependency>       <groupId>jdom</groupId>       <artifactId>jdom</artifactId>       <version>1.0</version>     </dependency>   </dependencies>      <build>     <sourceDirectory>src/main</sourceDirectory>     <unitTestSourceDirectory>src/test</unitTestSourceDirectory>     <unitTest>       <includes>         <include>**/*Test.java</include>       </includes>     </unitTest>   </build>    </project>

The important item is the extend element, which specifies a parent POM to inherit from.


Tip: Prior to Maven 1.0.2, you had to use the ${basedir} property to prefix directories defined in the POM (such as for the extend tag, or for the sourceDirectory tag). Otherwise, the project would not build correctly when using the Multiproject plug-in. This is not necessary anymore.

3.2.2. What just happened?

You created a common configuration for a series of subprojects. You extracted common information to the common/project.xml file, and you did this by using the extend element.


Tip: In Maven 2 it will be possible to define build elements to be inherited by subprojects in a special section in the POMs of the parent projects. Thus, you will not need to have a common/ directory, as you do for Maven 1.

This extend element tells Maven to inherit not only from a parent's project.xml, but also from the parent's maven.xml and project.properties files. Actually you can't decide what you inherit: it's everything or nothing. If the common/maven.xml file defines a custom goal, it will be available to the subproject, and if common/project.properties defines a set of properties, they will also be available to a subproject. Although not discussed in this book, it is possible to have any number of inheritance levels; a subproject could extend an intermediate project.xml which, in turn, could extend another project.xml. Each extension brings with it properties from project.properties and goals from maven.xml.

Note that common/project.xml contains the following element with references to ${pom.groupId} and ${pom.artifactId}:

<url>http://www.mavenbook.org/projects/${pom.groupId}/${pom.artifactId}</url>

The value of the url element is evaluated for each subproject, and in the case of the core project, this value would translate to http://www.mavenbook.org/projects/mdn/qotd-core. The common/project.xml file defines the value for the groupId, and each subproject's id element is used as the artifactId. In this example, you have configured a single project.xml which sets the structure of each subproject's URL. Each subproject will have a different URL because variable substitution is performed for each specific subproject.

As mentioned previously, this example uses an RSS and Atom parsing framework known as Rome, and the core project defines two dependencies in core/project.xml: the Rome library and JDOM.


Note: References to variables in the common project.xml file are evaluated in the context of each subproject. ${pom} referenced in common/project.xml is replaced with the POM object of each subproject.

3.2.3. What about...

...the precedence level between properties defined in your user home, on the command line, in your parent projects (there can be several inheritance levels), and in your project?

This is something important to keep in mind. The properties are resolved in the following order (the last property set takes precedence over the previous ones), as shown in Figure 3-3:

  • [parent]/project.properties

  • [parent]/build.properties

  • [project]/project.properties

  • [project]/build.properties

  • [userhome]/build.properties

  • System properties

Figure 3-3. Level of precedence for Maven properties




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