Up: Part III

A A Brief Tour of Maven

In this chapter we’ll discuss the Maven build tool and some of the basics of configuration and usage. Maven is what Lift uses for build management, so becoming acquainted with Maven is important to getting the most out of Lift. If you’re already familiar with Maven you can safely skip this chapter.

A.1 What is Maven?

Maven is a project management tool, as opposed to simply a build tool. The Maven site [W]  [W] http://maven.apache.org/ describes the goals of Maven as:
As a project management tool, Maven goes beyond just controlling compilation of your code. By default, Maven comes equipped not only to perform development-centric tasks, but it can generate documentation from your code and for your project website. Everything in Maven is controlled via the pom.xml (Project Object Model) file, which contains both information and configuration details on the project. We’ll be covering some of the basic aspects of the POM through the rest of this chapter [X]  [X] A complete POM reference is available at http://maven.apache.org/pom.html.

A.2 Lifecycles, Phases and Goals

Maven is designed around the concept of project lifecycles. While you can define your own, there are three built-in lifecycles: default, clean and site. The default lifecycle builds and deploys your project. The clean lifecycle cleans (deletes) compiled objects or anything else that needs to be removed or reset to get the project to a pristine pre-build state. Finally, the site lifecycle generates the project documentation.
Within each lifecycle there are a number of phases that define various points in the development process. The most interesting lifecycle (from the perspective of writing code) is default. The most commonly used phases in the default lifecycle are [Y]  [Y] A full listing of lifecycles and their phases is at http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html:
Maven is typically run from the command line [Z]  [Z] There are IDE plugins for Maven for most major IDEs as well by executing command “mvn <phase>”, where <phase> is one of the phases listed above. Since phases are defined in order, all phases up to the one you specify will be run. For example, if you want to package your code, simply run “mvn package” and the compile and test phases will automatically be run. You can also execute specific goals for the various plugins that Maven uses. Execution of a specific goal is done with the command “mvn <plugin>:<goal>”. For instance, the compile phase actually calls the compiler:compile goal by default. A common usage of executing a goal for Lift is the jetty:run goal, which compiles all of your code and then runs an instance of the Jetty [A]  [A] http://www.mortbay.org/jetty/ web server so that you can exercise your app. The jetty plugin is not directly bound to any lifecycle or phase, so we have to execute the goal directly.
One final note is that you can specify multiple phases/goals in one command line, and Maven will execute them in order. This is useful, for instance, if you want to do a clean build of your project. Simply run “mvn clean jetty:run” and the clean lifecycle will run, followed by the jetty:run goal (and all of the prerequisites for jetty:run, such as compile).

A.3 Repositories

Repositories are one of the key features of Maven. A repository is a location that contains plugins and packages for your project to use. There are two types of repository: local and remote. Your local repository is, as the name suggests, local to your machine, and represents a cache of artifacts downloaded from remote repositories as well as packages that you’ve installed from your own projects. The default locations of your local repo will be:
You can override the local repository location by setting the M2_REPO environment variable, or by editing the <home>/.m2/settings.xml file [B]  [B] Details on customizing your Maven installation are available at http://maven.apache.org/settings.html.
Remote repositories are repositories that are reachable via protocols like http and ftp and are generally where you will find the dependencies needed for your projects. Repositories are defined in the POM; listing A.3↑ shows the definition of the scala-tools.org release repository where Lift is found [C]  [C] scala-tools.org also has a snapshots repository where nightly builds of the scala-tools projects are kept. Maven has an internal default set of repositories so usually you don’t need to define too many extra repos.
Defining a repository
<repositories>
  <repository>
    <id>scala-tools.org</id>
    <name>Scala Tools Maven2 Repository</name>
    <url>http://scala-tools.org/repo-releases</url>
  </repository>
</repositories>
As a final note, sometimes you may not have net access or the remote repos will be offline for some reason. In this case, make sure to specify the “-o” (offline) flag so that Maven skips checking the remote repos.

A.4 Plugins

Plugins add functionality to the Maven build system. Lift is written in Scala, so the first plugin that we need to add is the Maven Scala Plugin; this adds the ability to compile Scala code in your project. Listing A.4↓ shows how we configure the plugin in the pom.xml file for a Lift application. You can see the Scala plugin adds a compile and testCompile goal for the build phase, which makes Maven execute this plugin when those goals are called (explicitly or implicitly). In addition, the configuration element allows you to set properties of the plugin executions; in this case, we’re explicitly specifying the version of Scala that should be used for compilation.
Configuring the Maven Scala Plugin
<plugin>         
  <groupId>org.scala-tools</groupId>         
  <artifactId>maven-scala-plugin</artifactId>         
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>               
        <goal>testCompile</goal>             
      </goals>           
    </execution>         
  </executions>         
  <configuration>           
    <scalaVersion>${scala.version}</scalaVersion>         
  </configuration>       
</plugin>

A.5 Dependencies

Dependency management is one of the more useful features of Maven. Listing A.5↓ shows a declaration of the Jetty dependency for the default Lift application. The details of the specification are straightforward:
Adding a Dependency
<dependency>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>jetty</artifactId>
  <version>[6.1.6,)</version>
  <scope>test</scope>
</dependency> 

A.5.1 Adding a Dependency

As an example, let’s say that you’d like to add a new library and you want Maven to make sure you’ve got the most up-to-date version. We’re going to add Configgy [E]  [E] Configgy’s home is http://www.lag.net/configgy/ as a dependency. Configgy is “a library for handling config files and logging for a scala daemon. The idea is that it should be simple and straightforward, allowing you to plug it in and get started quickly, writing small useful daemons without entering the shadowy world of java frameworks.”
First we need to tell Maven where we can get Configgy, so in the <repositories> section add the following:
Adding the Configgy repo
<repository> 
  <id>http://www.lag.net/repo/</id> 
  <name>http://www.lag.net/repo/</name> 
  <url>http://www.lag.net/repo/</url> 
</repository>
Then in the <dependencies> section add:
Adding the Configgy dependency
<dependency> 
  <groupid>net.lag</groupid> 
  <artifactid>configgy</artifactid> 
  <version>[1.2,)</version> 
</dependency>
That’s it, you’re done. The next time you run Maven for your project, it will pull down the Configgy jars into your local repository. Maven will periodically check for new versions of dependencies when you build, but you can always force a check with the “-U” (update) flag.

A.6 Further Resources

Obviously we’ve only scratched the surface on what you can with Maven and how to configure it. We’ve found the following set of references useful in learning and using Maven:

A.7 Project Layout

One of the things that allows Maven to work so well is that there is a standardized layout for projects. We’re not going to cover all of the standard locations for parts of your Maven project, but we do want to highlight a few locations that are important to Lift applications specifically:
<application_root>/src/main/scala This directory is where you place your Scala source, such as snippets, model objects, and any libraries you write. The subfolder structure follows the traditional Java packaging style.
<application_root>/src/main/resources This directory is where you would place any resources that you want to go into the WAR file. Typically this is used if you want to add entries to the META-INF directory in the WAR, since normal web resources should be placed under the webapp/WEB-INF directory.
<application_root>/src/main/webapp All of the web and static content for your application, such as images, XHTML templates, JavaScript and CSS are placed under this directory. This is also where your WEB-INF directory (and the configuration files it contains) goes. This directory is essentially what is packaged into the WAR in addition to the output from your Scala sources.
<application_root>/src/main/webapp/templates-hidden This is a special location for templates. As we discuss more in sections 5.1↑ and 4.5.7↑, templates placed in this directory cannot be viewed directly by clients, but are available to other templates.
<application_root>/src/test/scala This directory is where you can put all of your test code. As with src/main/scala, the subfolder structure follows the traditional Java packaging style.
Up: Part III

(C) 2012 Lift 2.0 EditionWritten by Derek Chen-Becker, Marius Danciu and Tyler Weir