I created this document for my team at work when I migrated all our ant builds to maven.

What is Maven
Maven is more than a build tool. It’s is a project management tool. Maven’s power lies in it approach – standards over flexibility – and code reusability using plugins.

Maven Principles

  • Convention over configuration
  • Declarative execution
  • Reuse of build logic
  • Coherent organization of dependencies

Using standard conventions saves time, makes it easier to communicate to others, and allows you to create value in your applications faster with less effort.

There are three primary conventions that Maven employs to promote a standardized development environment:

  • Standard directory layout for projects
  • The concept of a single Maven project producing a single output
  • Standard naming conventions

Why we are migrated to Maven from Ant builds
Using Ant we ran into the following issues:

  • Lack of common approach OR copy, paste, edit approach
  • A lot of time spent by developers configuring the build
  • Any changes to project structure would mean changes to build and more configuration
  • Configuring multi-module projects and dependencies were a huge task and required build expertise
  • Not everyone knows how to write Ant build scripts

So despite creating and encapsulating the common tasks such as compile, compile-tests, run-tests, etc. into a build-common.xml Ant build file, it still wasn’t enough. By the way, in Maven, you don’t need to write common tasks as the above. All these come bundled via plugins in Maven. Behold the power of Maven plugins. Shout Hallelujah!

Maven can prove to be indispensable and IMHO, brings more value and speed than Ant when starting a new team and new projects. For example, one would not need to spend time creating, encapsulating, and testing the common tasks in a build-common.xml.

Of course, the previous statement/paragraph is not intended to downplay the benefits and value that Maven provides to projects migrating from Ant as you will see shortly.

Before we move on, it would be worth mentioning that “Standards over Flexibility” does not imply that Maven isn’t extensible. You may override some or all of the defaults – for example, you may choose to change the default directory names or change the default lifecycle – but it may prove to be counter productive and time-consuming in the long run. To quote Jerry Seinfeld,

“The road less traveled is less traveled for a reason”.

Maven Build Life Cycle

Every project follows a certain execution path or a process for building and distributing a particular artifact. Maven has standardized this process so that it is only necessary to learn a small set of commands to build any Maven project.

Lifecyle Phases – Description
validate – validate the project is correct and all necessary information is available
generate-sources – generate any source code for inclusion in compilation.
process-sources – process the source code, for example to filter any values.
generate-resources – generate resources for inclusion in the package.
process-resources – copy and process the resources into the destination directory, ready for packaging.
compile – compile the source code of the project.
process-classes – post-process the generated files from compilation, for example to do bytecode enhancement on Java classes.
generate-test-sources – generate any test source code for inclusion in compilation.
process-test-sources – process the test source code, for example to filter any values.
generate-test-resources – create resources for testing.
process-test-resources – copy and process the resources into the test destination directory.
test-compile – compile the test source code into the test destination directory.
test – run tests using a suitable unit testing framework. should not require the code be packaged or deployed.
prepare-package – perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. (Maven 2.1 and above)
package – take the compiled code and package it in its distributable format, such as a JAR.
pre-integration-test – perform actions required before integration tests are executed. This may involve things such as setting up the required environment.
integration-test – process and deploy the package if necessary into an environment where integration tests can be run.
post-integration-test – perform actions required after integration tests have been executed. This may including cleaning up the environment.
verify – run any checks to verify the package is valid and meets quality criteria.
install – install the package into the local repository, for use as a dependency in other projects locally.
deploy – done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
clean – cleans up artifacts created by prior builds.
site – generates site documentation for this project.
How do you execute a certain lifecycle phase? By default this is specified in the POM. The “packaging” element in the POM defines the phase to execute and by default it is “jar”. So Maven will execute the above phases starting with validate up to and including packaging (jar). You can add extension points or customize your build lifecycle by configuring existing plugins or creating and adding your own plugin. You can also run a certain phase from the command line as:

mvn compile

The above will run all phases from validate up to and including the compile phase. A phase is a step in the build lifecycle. Phases are mapped to underlying goals. You can even execute a certain goal in a phase. For example,

mvn archetype:create -DgroupId=com.plexibus -DartifactId=com.plexibus.common

The above goal will create a directory with the same name given as the artifactId or in other words a new Java project with a standard structure as espoused by Maven. You can execute multiple phases as well:

mvn clean compile

Maven Standard Directory structure

Files – Description
src/main/java – Application/Library sources
src/main/resources – Application/Library resources
src/main/filters – Resource filter files
src/main/assembly – Assembly descriptors
src/main/config – Configuration files
src/test/java – Test sources
src/test/resources – Test resources
src/test/filters – Test resource filter files
LICENSE.txt – Project’s license
README.txt – Project’s readme
target – Generated output directory

Project Object Model

The POM is defined in a pom.xml file that contains all the information necessary to build the project, generate reports, and configure plugins. An example POM is show below:


	4.0.0
	for
	bar
	jar
	1.0.0-SNAPSHOT
	bar
	
	
		
			junit
			junit
			4.4
			test
		
	

Maven model: http://maven.apache.org/ref/2.0.8/maven-model/maven.html

Maven Repositories

There are three types of Maven repositories

  • Local repository on the developer machine. This is usually located at ${user.dir}/.m2/repository
  • Shared internal repository or Corporate repository. Artifactory is a decent tool that can be used as a corporate repository
  • Public repository. By default you are pointed to http://repo1.maven.org/maven2. Although you can add additional repositories by configuring Maven (settings.xml), you should follow the standard operating practice that is point your Maven install to your organization's corporate Repository. Repositories are essentially directories with a certain structure.

Installing Maven
Download and install maven from here. Once you have installed it, add an environment variable

M2_HOME=<MAVEN_INSTALL_DIR>

Edit the settings.xml in $M2_HOME/conf to point to your organization's corporate Repository.

Maven frequently used commands

Create a new project

mvn archetype:create -DgroupId=foo -DartifactId=bar

or

mvn archetype:generate -DgroupId=foo -DartifactId=bar -B

or

mvn archetype:generate -DgroupId=foo -DartifactId=bar -Darchetype.interactive=false

Create a new web application project

mvn archetype:create -DgroupId=foo -DartifactId=barwebapp -DarchetypeArtifactId=maven-archetype-webapp

Clean up generated artifacts

mvn clean

Clean and compile the project

mvn clean compile

Clean, compile, and run unit tests

mvn clean compile test

Clean, compile and package to create an artifact (default jar)

mvn clean package

Clean, package up the artifact and install it into your local repository

mvn clean package install

Clean, package up the artifact and generate a website (documentation)

mvn clean package site

Generate Eclipse IDE settings

mvn eclipse:clean eclipse:eclipse -DdownloadSources=true

Creating a simple project in Maven

mvn archetype:create -DgroupId=foo -DartifactId=bar

Maven will create a directory with the name "bar". Change to the "bar" directory and you will see a generated pom.xml, and "src" directory with sub-directories such as "src/main", "src/main/java", "src/test", "src/test/java".

Multi-module project
Multi-module projects are slightly different in that each module (parent included) has a pom.xml.

Say you want a directory structure like:

bar
|-> baz
|-> bam

mvn archetype:create -DgroupId=foo -DartifactId=bar

This will create a "bar" sub-directory with a "pom.xml" and "src" sub-directory.
Change to the "bar" sub-directory and delete the "src" folder. Edit the pom.xml. Change the packaging element to "pom" instead of "jar".
Now from within the "bar" directory, execute the following command:

mvn archetype:create -DgroupId=bar -DartifactId=baz
mvn archetype:create -DgroupId=bar -DartifactId=bam

This will create the following modules (directories), "baz" and "bam" with their own pom.xml files and "src" sub-directories. You will also notice that the parent pom.xml (in "bar" directory) has been updated to reflect the child modules: "baz" and "bam".

You can now build "bar" which will in turn build the child modules "baz" and "bam"

mvn clean package

The parent pom (in bar) is inherited by the sub module poms. So you could effectively define global elements such as dependency like "junit" in the parent pom which will be inherited by the sub module poms. A good case for reuse and reduced redundancy. Defining the same element in the sub module will override the element definition in the parent module.

Maven and setting up Eclipse
Eclipse needs to know the path to the local maven repository. Therefore the classpath variable M2_REPO has to be set.

  1. Select Window > Preferences. Select Java > Build Path > Classpath Variables.
  2. Create a new M2_REPO variable and point it to your $\{user.dir\}/.m2/repository folder.
  3. Next, from the menu bar, select Window > Preferences. Select the Run/Debug > String Substitution. Add a new variable e.g. maven_exec.
  4. When you set up a new external launcher (from the menu bar, select Run > External Tools. Select Program) you can refer to maven_exec in the "Location" field. And add $\{project_loc\} to the "Working Directory" field. And then specify the maven goals of your choice in the arguments such as: clean package
  5. You can set up multiple launch configurations such "clean, compile", "clean package site", "clean package install", etc.

Deploying artifacts to Corporate Repository

If you want to deploy a certain artifact or an artifact that isn't available yet in one of the public remote repositories, you can do the following:

mvn deploy:deploy-file -DrepositoryId=artifactory
-Durl=http://somerepository.com
-DgroupId=com.ibm.mq -DartifactId=com.ibm.mqjms -Dversion=5.3
-Dpackaging=jar -Dfile=com.ibm.mqjms.jar

*Note:* You should never have to use the deploy command since you should have your continuous integration tool deploy the artifacts to your organization's corporate repository.

Maven Global and User settings
Maven has two settings files, one in the Maven installation directory (under conf) - settings.xml (global settings), and one in the user's home directory. They are merged, and the latter overrides anything in the former. If you want to override the global settings you could pass an additional parameter (-Dorg.apache.maven.global-settings) when you run maven commands as follows:

mvn clean install -Dorg.apache.maven.global-settings=c:\new_global_settings.xml

Note that you are only overriding the global settings here. Therefore if you have a user settings xml, that will still be applied. The -D argument above is deprecated in 2.1.x. Use -gs instead.

mvn clean install -gs c:\new_global_settings.xml

If you want to override user settings, you could pass the new user settings as follows:

mvn clean install -s c:\new_user_settings.xml

Tagging, Branching, Releasing using Maven
Coming soon!

Troubleshooting tips

Maven help

mvn --help

OutOfMemoryError
If you are getting OutOfMemoryErrors when doing a build, try increasing the max heap and PermGen space sizes. You can do this by setting the MAVEN_OPTS variable

set MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=256m
export MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=256m

Debug
The debug option is very useful when you find yourself in "classloader hell"(conflicting library versions or unwanted jars in your classpath). The debug option makes it easy to see where each library is coming from

mvn -X

Debugging test failures
Surefire, which is the default Maven test runner, outputs all reports as a set of xml and text files. Any test failure details and stacktraces end up in those files and not the console. The output can be redirected to the console temporarily by adding the following option

mvn -Dsurefire.useFile=false

Non-recursive option
Executing a Maven goal for a module will default execute the goal for any modules below it in the heirarchy. If you specifically wish to run the goal for this module only (and not it's children) you can use the non-recursive option:

mvn -N

Skip compiling unit tests

mvn -Dmaven.test.skip=true

Skip running unit tests

mvn -DskipTests

or you could set the skipTests property (maven-surefire-plugin configuration) to true in the pom

Ignore (do not fail) on test failures
This could be useful when you don't want builds to fail, such as clover builds.

mvn -Dmaven.test.failure.ignore=true

Generating clover reports without generating site
The following command will generate clover reports without generating the entire website.

mvn clover:instrument clover:clover

Move Local Maven Repository
See here on how to do this.

References
htt://maven.apache.org