Maven Architecture

Maven at its core is based around its plug-in architecture and the POM. This architecture uses the Jelly scripting language (which we examine in the ) for its goal processing. The POM, as the project descriptor, controls what features your project will use, what libraries it depends on, who is working on the project, project mailing lists, and so forth. All installed plug-ins are stored in your MAVEN_HOME directory. Each plug-in that is deployed is in a named directory, such as maven-java-plugin-1.3, and under that directory are a number of files, such as plugin.jelly, plugin.properties, project.properties, and project.xml. A Maven plug-in is similar to a Maven project. Each plug-in consists of two items: goals and properties. Goals are items that you as a developer can execute to perform an action on your project. Some example goals are:

Every plug-in has executable goals. To see what each goal does, you can either look at the plug-in documentation on the Maven Web site or type maven -g (which displays all available goals for installed plug-ins). Most goals are not stand-alone, which means they rely on other goals being executed before them. To better understand this, let's look at one of the core plug-ins and examine its goals:

Java plugin.jelly file
<?xml version="1.0"?>
<project xmlns:j="jelly:core"
 xmlns:ant="jelly:ant"
 xmlns:define="jelly:define"
 xmlns:maven="jelly:maven">
 <goal name="java:prepare-filesystem"
 description="Create the directory structure needed to compile">
 <ant:mkdir dir="${maven.build.dest}"/>
 </goal>
 <goal name="java:compile"
 description="Compile the project"
 prereqs="java:prepare-filesystem">
 ....
 </goal>

As you can see from this Jelly file, the plug-in is essentially an XML file with custom processing that will be interpreted by the Jelly engine. First we start with a project element, which allows you to create namespace declarations. These declarations are then interpreted by Jelly, and it loads those tag files. For right now, don't worry about these too much; we discuss them in more detail in the section. Now we need to concentrate on the java:compile goal. As you can see, there is a prereqs attribute that describes what goals need to execute prior to this goal being attained. There is also a description attribute that will display when you type maven -g on the command line. Later we use a similar technique when we write our maven.xml file to execute a custom goal of our definition. Plug-in properties allow you to modify the default behavior or to specify things like additional source directories specific to that plug-in. Most of the plug-ins properties that can be set are documented on the Maven site (if they are distributed with Maven) or in the plug-in's own documentation. If neither of these is available, you can go into the plug-in's directory and view its plugin.properties file. This file should not be modified. Here is an example of one from the CruiseControl plug-in:

maven.cruisecontrol.config=${basedir}/cruisecontrol.xml maven.cruisecontrol.schedule.interval=300
maven.cruisecontrol.checkout.dir=${basedir}/checkout maven.cruisecontrol.logs.dir=${basedir}/target/cc-logs maven.cruisecontrol.goals=scm:update|clean test|site:deploy maven.cruisecontrol.home=CC_HOME_NOT_SET maven.cruisecontrol.mail.host=localhost maven.cruisecontrol.mail.defaultsuffix=DEFAULT_SUFFIX_NOT_SET maven.cruisecontrol.mail.subjectprefix=[BUILD]

These are all properties that you can set in your own project.properties file. In fact, a number of these are required to be set, such as the cruisecontrol.home property, to tell the plug-in where you have installed CruiseControl (see for more information about CruiseControl). Now that we've examined some of the Maven underpinnings, the next step is to look at how Maven works. The easiest way to do this is to run Maven in debug mode by typing maven -X jar:jar. This executes the jar command, which first builds your classes, then runs the unit tests and finally jars your project for deployment or distribution, as shown below.

You should see a lot of text flying by as the debug output goes to the console. I'll walk through some of the initial phases of Maven:

  1. Sets references: Maven sets up all of its internal references, including the JAR dependency locations, test source, Java source, and whatever other references you have defined specific to your project. These also include project and personal properties files.
  2. Downloads dependencies: If there are missing dependencies in the local repository, Maven attempts to download these, according to your maven.repo.remote property (which defaults to ibiblio.org/maven).
  3. Updates plug-in dependencies: Maven updates the class path dependencies with internal dependencies required by installed plug-ins.
  4. Prepares filesystem: If the target directory has not been created, Maven creates it and populates it with required directories according the plug-in's goals.
  5. Scans files: Maven scans for package.html in the source tree to exclude automatically.
  6. Builds: It builds the Java source.
  7. Unit-tests: It compiles and runs unit tests.
  8. Jars: It jars classes for deployment and places them in the target directory.

Maven processes the following properties files in this order:

  1. ${project.home}/project.properties
  2. ${project.home}/build.properties
  3. ${user.home}/build.properties

So, each project can override Maven properties, and each user can override project and Maven properties.

Maven Properties

There are a number of properties specific to Maven that you can override to provide a custom look and feel for your generated site, to turn on and off XML declarations in HTML headers, and other behavior. Here are some of the properties that you may want to change depending on your needs: