Introduction to Apache Maven

Posted by buildmeister on April 11th, 2007
Filed under:  build scripting  java  tools 
There are 0 comments on this article.
Bookmark and Share

Introduction

Apache Maven is an interesting and relatively new Java-based build tool. From a build scripting point of view, Maven can be seen as a potential replacement for Apache Ant. The main difference is that rather than specifying a detailed set of build commands (as in an Ant script), Maven follows a more rule or goal-based approach. Most of the goals that you would typically require when building a Java project, i.e., compiling, testing, creating distribution archives and so on are already embedded in Maven's project lifecycle. The main advantage of this approach is that there is potentially significantly less scripting required to implement a build process.

Maven also has advanced build project management capabilities. This includes the capability for specifying and resolving Java library dependencies from a central project repository (something which can rapidly become overwhelming in any large scale Java project). As well as automatically generating project documentation (code style reports, metrics, developer activity, change logs) and ultimately the construction of a complete project web site.

There are two versions of Apache Maven: Maven 1 and Maven 2 both of which have significantly different code bases and implementation details. Maven 1 is in maintenance mode (no new features are being added), therefore this article will concentrate on discussing Apache Maven 2.

Key Concepts

repository - a local or central repository of dependent Java archives.

project object model (POM) - a description of the project to be built, its contributers, dependencies and reports..

goals - a discrete part of an end-to-end build process, i.e. compile, test, package.

dependencies - the set of Java libraries (and their versions) that are required to build a project.

transitive dependencies - the dependencies of dependencies, i.e. if you require a library X at version 1 it requires (and resolves itself) any other libraries it needs.

Maven has a number of concepts which it is worth discussing and understanding as follows:

  • The repository

One of the main differences between Apache Maven and other build tools is that Maven maintains a repository of dependent Java archives for each user. What this means is that when you run Maven and require specific versions of Java libraries to build against, Maven checks for the existence of these libraries from a central repository and downloads them to your own local repository. By default, this central repository is hosted on the Internet at http://www.ibiblio.org/maven2 - which means that you will require an Internet connection for for downloads to occur successfully, however, for more secure environments you can also create a central repository on your organizations Intranet..

  • Configuration files

Maven uses a number of configuration files to manage its environment and execution as follows:

- pom.xml
The pom.xml file is required for each project being built and it is where you place the description of the project in what Maven calls Project Object Model (POM) format. Maven sometimes refers to this file as the project descriptor.

- settings.xml
The settings.xml file contains property values for Maven and its plug-ins, it is usually used to override specific settings in the pom.xml file. It is usually created by individual users when they want to override settings.

- profiles.xml
The profiles.xml file contains grouping of properties that can be applied to a build execution, for example an integration build, release build, deployment to UAT build and so on.

  • Goals

In a similar way that you execute targets via Ant, i.e. ant compile, with Maven you execute goals, i.e. mvn compile. The main difference is that with Ant you have to define these targets yourself in the build.xml file, whereas with Maven a large number of them are already pre-defined as part of a standard "build lifecycle". These pre-defined goals encompass a large part of the build process from compilation to distribution, to deployment and documentation. If you still need to create custom goals then you can also create custom plugins (see below) that implement a discrete set of operations (Maven calls these goals its "Mojo") and bind them to part of the build lifecycle in the pom.xml file.

  • Plugins

Maven is built from a small core extended by plug-ins; a comprehensive number of plug-ins are already distributed or automatically downloaded with Maven but there are more that are available that are not part of the standard distribution. Plugins allow for the reuse of common build logic across multiple projects. They do this by executing an "action" (i.e. creating a Java Web archive or executing JUnit tests) in the context of the Project's Object Model. Plugin behavior can be customized through a set of unique parameters which are exposed by a description of each plugin goal.

An Example

An example of an Maven pom.xml file to build a set of Java classes (for the Hotel de Java application web front end) is given below::

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.sourceforge.hdjweb</groupId>
    <artifactId>HDJWeb</artifactId>
    <packaging>war</packaging>
    <version>1.0-alpha-1</version>
    <name>HDJWeb</name>
    <url>http://hoteldejava.sourceforge.net</url>

    <dependencies>
        <dependency>      
            <groupId>net.sourceforge.hoteldj.ejb</groupId>
            <artifactId>HDJEJB</artifactId>
            <version>1.0-alpha-1</version>
            <type>ejb</type>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <webResources>
                        <resource>
                            <directory>${project.basedir}/WebContent</directory>
                            <includes>
                                <include>**/*.jsp</include>
                                <include>theme/*</include>
                                <include>WEB-INF/geronimo*.xml</include>
                                <include>WEB-INF/web.xml</include>
                            </includes>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <scm>
        <connection>         
            scm:svn:https://hoteldejava.svn.buildmeister.net/svnroot/hoteldejava
        </connection>
        <developerConnection>
            scm:svn:https://hoteldejava.svn.buildmeister.net/svnroot/hoteldejava
        </developerConnection>
        <tag>HEAD</tag>
        <url>
            http://hoteldejava.svn.buildmeister.net/viewvc/hoteldejava/
        </url>
    </scm>

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>
                    maven-project-info-reports-plugin
                </artifactId>     
                <reportSets>
                    <reportSet>
                        <reports>
                            <report>dependencies</report>
                            <report>project-team</report>
                            <report>mailing-list</report>
                            <report>issue-tracking</report>
                            <report>license</report>
                            <report>scm</report>
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
        </plugins>
    </reporting>

</project>

If this file was used to build the application then the output result would look similar to the following:

>mvn package
[INFO] Scanning for projects...
[INFO] -------------------------------------------------------------------------
---
[INFO] Building HDJWeb
[INFO] task-segment: [package]
[INFO] -------------------------------------------------------------------------
---
Downloading: http://repo1.maven.org/maven2/junit/junit/3.8.1/junit-3.8.1.pom
998b downloaded
...
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 10 source files to C:\Builds\HDJWeb\target\classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [war:war]
[INFO] Exploding webapp...
[INFO] Assembling webapp HDJWeb in C:\Builds\HDJWeb\target\HDJWeb-1.0-alpha-1
[INFO] Copy webapp webResources to C:\Builds\HDJWeb\target\HDJWeb-1.0-alpha-1
[INFO] Copy webapp webResources to C:\Builds\HDJWeb\target\HDJWeb-1.0-alpha-1
[INFO] Generating war C:\Builds\HDJWeb\target\HDJWeb-1.0-alpha-1.war
[INFO] Building war: C:\Builds\HDJWeb\target\HDJWeb-1.0-alpha-1.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Tue Jul 31 10:21:33 BST 2007
[INFO] Final Memory: 5M/10M
[INFO] ------------------------------------------------------------------------

In this build script a Web archive called HDJWeb-1.0-alpha-1.jar will be built. This version number is managed by Maven and is used so that different Java library versions can be stored in the repository for different projects. When you first start a Maven build a large number of plugins will be downloaded to your local repository (in this example you can see that information about JUnit is being downloaded). Note that unlike Ant, the pom.xml file does not need to specify the details of how to compile and package your application. - Maven knows how to do this automatically. Instead the pom.xml file describes information about the project, its build time dependencies and the configuration of any plugins that are to be executed.

In more detail example the first part of the pom.xml file, lines 1-11 defines some basic information about the project and the organization developing it. Lines 13-20 specify the list of third party and internally developed libraries that this project is dependent upon, in the case version 1.0-alpha-1 of HDJEJB This information is used to download the specific version of this library from the central repository for building against.

Lines 22-43 illustrate how you can configure Maven's plugins. In this case the maven-war-plugin is being configured to point to the locations of the applications web resources. If your applications directory structure was implemented exactly as the maven-war-plugin expects then there would be no need for this section. However with the use of IDEs and existence of legacy applications you sometimes do not get a choice in this matter. Configuring any of Maven's other core and contributed plugins works in exactly the same way. Note that when the Maven build was executed the package goal for the application was specified, since the packaging type is specified on line 8, Maven knows to call that maven-war-plugin rather than the maven-jar-plugin for example.

Lines 45-56 specifies the SCM connection that is to be used for the project - in this case Subversion. This information is used by plugins which require SCM repository information, such as the maven-release-plugin which can be used to prepare and perform a release. It is also used to populate some of the reports that Maven can automatically generate.

Reporting is one of Maven's most powerful capabilities as it allows you to generate a complete project web site. Lines 58-79 illustrate how you can configure Maven to produce a number of reports including the dependency list, SCM information, information on the project team, mailing lists and so on. The information for these reports will be automatically collected and generated when you execute the maven-site-plugin. As well as incorporating reports you can also add your own web pages, FAQs and complete navigation hierarchies into your own generated project web site. An example Maven generated project web site for the complete HotelDeJava application is illustrated below:

HotelDeJava project web site

Summary

This article was intended as a rapid introduction to some of Apache Maven's capabilities. Maven is a powerful and evolving too and in comparison to Apache Ant has a number of distinct advantages. Its foundation of plugins and goals should make it much easier to maintain and implement new project build processes. Its dependency capability is also a big advantage for more complex Java development projects and its project website capability is unique. Some of these capabilities could be achieved with Ant, for example you can implement re-usable routines using Ant's import and macro capabilities and you could use Apache Ivy for dependency management. However, Maven is still a very strong proposition for complex and greenfield project build processes.

References

Bookmark and Share

Comments

There are no comments on this article.

Back to Top

Submit a new comment

All fields in bold are required.