Migrating a Project from Ant to Maven

A fair number of projects use Ant as a build system, and you will want to migrate to Maven.

How do I do that?

Start from scratch. Create a default Maven template, and then move your code to the proper directories. Do not try to fit Maven to your own project's directories and build locations. Maven is more than a build tool; it is a standard way to think about project layout and management. If you attempt to fit Maven to your project's idea of a build, you'll end up using Maven as it was never intended. If your project consists of a complex build.xml file which produces a number of different deliverables, you will need to "componentize" your project and follow the model for multiprojects described in Chapter 3. You will also need to start moving your project's directory structure toward the standard Maven project directory structure presented throughout this book. In other words, don't try to "shoehorn" Maven onto your project.

If you are interested in migrating to Ant, but you don't have time to stop development, you can always use Maven to call your existing Ant targets. If you do this, you'll miss out on a large part of the benefit of using Maven, but it is a possibility. For more information, see the informative "Migrating from Ant" document located at http://maven.apache.org/using/migrating.html.

What about...

...flexibility and choice?

Flexibility and choice are part of the original problem. We promise that Maven will change the way you approach building and maintaining your project, but it is important to use Maven as Maven was intended to be used. What are the differences between Maven and Ant? Where Ant offers building blocks in the form of reusable tasks such as copy, move, delete, and junit, Maven offers reusable build processes. Maven is a "build container" which allows you to reuse build processes over a series of projects. Take unit testing as just one example. With Ant, you would perform a JUnit test by including the following in your project's build.xml file:

<junit printsummary="yes" haltonfailure="yes">
  <classpath>
    <pathelement location="${build.tests}"/>
    <pathelement path="${java.class.path}"/>
  </classpath>
  
  <formatter type="plain"/>
  
  <test name="my.test.TestCase" haltonfailure="no" outfile="result">
    <formatter type="xml"/>
  </test>
  
  <batchtest fork="yes" todir="${reports.tests}">
    <fileset dir="${src.tests}">
      <include name="**/*Test*.java"/>
      <exclude name="**/AllTests.java"/>
    </fileset>
  </batchtest>
</junit>

This snippet leaves out the definition of the various paths and variables such as build.tests and java.class.path, and it also leaves out the definition of Ant targets. In addition to some sort of unit test target, you'll also need to define a target to compile the source and the unit tests, and a target to create the destination directories. Every project needs to define the same logic just to perform a unit test. To this end, most Ant projects end up using a similar directory structure, and build logic is reused by just copying and pasting target definitions into a build.xml file. Over time, as projects become more complex and customized, directory standards evolve and each project tends to have a different approach to compilation, testing, and packaging; over time, the build.xml file becomes a project in and of itself. The larger your custom Ant build file is the more entropy creeps into your build process. Ant is less a build tool than it is a language which provides a build-specific API. While Ant 1.6 has Ant libraries and macros, Ant is still a long way from achieving the global reusability present in Maven.

With Maven, the Test plug-in defines logic common to all projects which need to compile and execute unit tests. The Test plug-in has captured best practices for compiling and executing unit tests, and it has made these best practices available to all projects. When you run maven test, Maven passes information from the POM to the Test plug-in, and the Test plug-in depends on a goal from the Java plug-in to perform the compilation. Nowhere in a Maven project are you explicitly telling the build container how to execute a JUnit test. If you were, you would be running into the same problem you faced in Ant. Just as you are not telling a Servlet container how to unpack your WAR file, you are not telling Maven how to build your project. Maven is a build container. It provides an abstraction layer to separate build logic from projects. Many people are initially attracted to Maven because it provides dependency management, but the main benefit of Maven is that it provides a standard development infrastructure across multiple projects. Dependency management is simply a byproduct of a standard development infrastructure.

Tip

Maven provides a development infrastructure and a uniform project layout, and to this end you should try to let Maven take care of most of the build process details. Instead of spending your valuable time writing build scripts, use Maven plug-ins and focus on writing your application.

The following chapters will show you how to tweak and customize Maven, but you need to make sure that you are not asking Maven to be another Ant. It is entirely possible to have one huge Maven project with a large maven.xml file full of Jelly script (see Section 2.1) that re-creates Ant's build.xml file, but if you do that you've missed the point of Maven entirely. If you find yourself including a great deal of build-related logic in your Maven build, you need to rethink your usage of Maven. A highly customized Maven build is an oxymoron; your Maven projects should leverage the existing plug-ins where possible. For example, if your project needs to compile Java source code and create a JAR file, use the Java plug-in and the JAR plug-in. If you ignore reuse through Maven's plug-ins and use Maven's Ant integration to reinvent wheels, you're better off not using Maven at all. Don't misuse Maven; use this tool as it was intended, and save yourself the bile.

Vincent says, "Neo, take the red pill..." and Tim says, "Resistance is futile."

Get Maven: A Developer's Notebook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.