Maven Tutorial

..FOR dummys, duffers and the perpetually confused.

Maven is a system for building software; a build automation tool that helps you ship out your software. If you have the vaguest understanding of Maven, you will also know that there is this thing called a POM file (pom.xml) which looks something like this :

Maven attempts to treat projects in an object oriented fashion, and one of the central tenants in Maven is that a project is an object. This project only needs to be described once, in one XML file called the POM file.

The project has a primary key, and this is defined by its coordinates: groupId, artifactId, and version. Effectively its package root, a name, and a version number.

That is basically the only prerequisite. Then you can just build your project, through your IDE most typically, or by using the Maven command line:

mvn clean install

which executes the clean lifecycle, and all phases up to the install phase in the default lifecycle. This is most commonly considered “building” a project.

A look at dependencies

The easiest thing to understand about Maven is also the most beautiful thing about Maven. Rather than managing a number of libraries across a number of projects, everything is tied to this thing called a maven reactor, a type of super library that contains all your libraries that you are using. You can see it in an .m2 directory under your user profile usually (It doesn’t really have a sexy name because it is best to be hidden. ‘Out of sight out of mind’ as they say).

maven3

The above example is from when I was working on my multi level pie chart project. It’s not too hard to see what was going on here. My pom.xml file looked like

As I was working on it I incremented the version number to 1.1, and after I did a build on the project, a new folder appeared called 1.1 with the file multi_level_pie_chart.jar in it.

The older versions are not deleted. There still hang around in the reactor. Who knows what other projects use these old versions?

Maven also allows you to point to the projects you need. As your own project is shipped to your .m2 directory, your own project is free to use whatever is in the .m2 directory. You just place in your dependency tags like so :

Maven will look for it in your .m2 directory. If it is not there then it will try and find the dependency on the web, and if it exists, download it to your .m2 directory. So in fact your dependency doesn’t have to exist in the .m2 directory. As long as you have an internet connection, it can exist as any Maven project in the internet.

As you work on multiple projects the maven reactor collates libraries that are needed as dependencies. On one project you may need JUnit1.4, but on another project you can only use JUnit1.3. The maven reactor neatly orders them based on version number.

maven4

If you hate configuration, Maven is for you.

Your project is its own source definition. There is no longer the hassle of faffing about with JAR files to make your project work, you no longer need to monkey around with pages and pages of configuration documents.

It’s all about the POM file. That’s what’s so cool about Maven!!

The configuration battles trying to get projects running across different IDEs, are no longer fought in the setups of IDEs. The battle front has been reduced to tinkering with the POM XML file.

Maven also allows for transitive dependencies. This dependency would only exists in the test phase:

A further five scopes are available, which describe a number of scenarios, such as having a dependency only at runtime, or that the dependency is provided by the application container.

A look at LifeCycles and Phases.

A lifecycle can contain many phases, and a phase contains many goals

maven5

Maven has 3 built in lifecycles.

Lifecycles contain a number of goals, grouped in phases. Maven has these lifecycles pre-configured for you to use, rather than offer an ad-hoc environment for you to chain them together as you please.

The clean :

Clean is what you would expect it to be. It blows away the target directory and that is about it. The reason that clean is not included in the default lifecycle is because a ‘clean’ is a time expensive activity. Once the target folder has been cleaned out, everything needs to be generated again (all the class files etc.). If clean were to be part of the default life cycle things would be slow because it would not be possible to build iterative changes. That is why the clean has been separated out of the default lifecycle.

The default :

The default life cycle is the main lifecycle that is used when building a project. I have enlargened the phases that you will encounter more often, and which are more important to understand.

maven6

Three of these phases should be familiar to most developers:

Compile – the software is compiled. Nothing too complicated here. Java code is converted to binary classes and put in the binary directory.

Test – All the unit tests are run. That’s all your JUnit tests that are sitting in your Test folder!

Package – after everything checks out as OK, the software needs to be bundled up ready for consumption. Ear file for JEE project, War file for Web project etc.

A couple of other commonly used phases

Validate – This checks all the directory structure is correction, that the conventions have been followed. Maven can’t work if people don’t follow the rules. The directory structure should look like this.

maven7

Install – (and his cousin deploy). These two are very similar. Install puts your packaged file, be it JAR, war, ear in the maven reactor (your .m2 directory). We have discussed this before. Doing an ‘install’ is usually considered doing a ‘build’

Deploy – takes this one step further, and moves your finished product to an internet location where it can be accessed from anywhere in the world.

[One word of warning, do not confuse the install and deploy phases with the actual deploying of your application. For example, these phases have nothing to do with the actual deploying of your web application to your server.]

Site :

Generates Documentation. We won’t cover this.

A look at Goals :

Goals describe actions. They are the atomic parts of Maven and are analogous to tasks in ANT. How they are accessed and manipulated is one of the hardest things to understand about Maven.

If you are familiar with ANT, ANT has tasks that are organized in a dependency tree. When one task executes, all the lower branches of the tree need to execute first. Well Maven is kind of similar, except that the tasks (the goals) are organized in a linear fashion.

So under the hood, Maven actually looks something like this :

maven8

It really is just a series of goals with no branching. Where ANT is tree-like, Maven is linear.

Plugins are a way that you can mess with this chain of goals, by attaching custom goals in certain phases.

A plugin, for example the wsimport plugin

If you visit the website https://jax-ws-commons.java.net/jaxws-maven-plugin/ you will see that it binds to the “generate-sources” phase. If you run a clean install, then the goal of this plugin, wsimport, will execute along with along the other goals in the generate-source phase.

Goals in plugins can also be executed independently:

mvn [plugin]:[goal]

In the above wsimport example, you would execute :

mvn jaxws:wsimport

While it is not advisable to change the phase in which a plugin executes, the phase can be overridden by modifying the execution XML like so :

So in summary, it is hard to understand what goals exist in Maven, and it is also hard to control where a goal executes in Maven. It is all under the hood stuff that only the plugins really know about. There really is little information about what goals exist in the default lifecycle.

 

 

A look at Project inheritance and project aggregation

All POMs inherit from the super pom. The super POM contains a lot of default configuration values. (eg. build.sourceDirectory = src/main/java) as well as other folder structures/properties that belong in the maven convention. You can look at the ‘effective pom’ which shows the merging of the pom files.

inheritance

It is also possible to make your projects inherit from other projects that you have created. Common configuration can be refactored out into the parent making maintenance much easier.

aggregation

Projects can also reference sub projects. This is called project aggregation.
This example shows how you might aggregate a number of child projects (called modules) in the parent project. When the parent project is built, all the modules will be built.

This example is a common pattern in JEE. It is a web application which is a packaging of a WAR and an EJB (as JAR) file, into an EAR file.

Note: you still need to define dependencies between projects, if order is important. For example, in the above, the WAR and JAR modules need to build before the EAR. In the EAR project I would expect to see something like this in the POM-file:

Anyway, I hope this tutorial was useful to some. It hasn’t covered everything, but I have tried to present the core concepts that people need to understand.


Posted in Tutorial | Tagged , , | Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

THREE_COLUMN_PAGE