The first time you use maven, making sense of its lifecycles, phases, goals and plugins is confusing.

Let’s demystify this.

1. Lifecycle and phases

When maven was created, its authors wanted to put in order all the messy build system that came before it, while keeping a lot of flexibility.

A lifecyle is a list of "phases", that is, just a step with a name, that do absolutely nothing on its own.

It is a representation of a generic list of steps for a build system.

3 such lifecycles were created:

  • clean with 3 phases;

  • default, with 23 phases;

  • site, with 4 phases.

Wait a minute, if those lifecycles do nothing on their own, how is anything accomplished?

2. Bindings

Maven allows you to bind a plugin to a phase. That’s what we call a binding.

Maven Generic Lifecycle with generic bindings

Here is a concrete example with the clean lifecycle with its 3 phases and its default bindings:

Maven Clean Lifecycle with its default bindings

3. Execution

To execute anything, you run mvn <phase>, and maven will:

  1. determine which lifecycle this phase belongs to;

  2. look up all the phases in that lifecycle up to the given phase;

  3. for each phase, check the list of bindings, and execute them.

For example, if I run mvn post-clean, maven will:

  1. determine that post-clean is part of the clean lifecycle;

  2. see that pre-clean and clean come right before post-clean;

  3. looking at pre-clean: no bindings exist, skip it;

  4. looking at clean: a single binding exists, maven-clean-plugin:clean. Run it.

  5. looking at post-clean: no bindings exists, skip it;

  6. done

(Sidenote: any plugin named maven-xx-plugin can be abbreviated to xx: the binding maven-clean-plugin:clean sis actually documented as clean:clean in the maven documentation)

4. Default Lifecycle with its default Bindings

The default lifecycle has 23 phases, but most don’t have default bindings.

The ones that do are bound to some "core" maven plugins:

Maven Default lifecycle and its default bindings

5. The Flexibility

Maven gives you the possibility to bind any number of plugins to any phase of the 3 lifecycles.

Some examples:

  • You want to ensure your company’s info appear in the pom.xml? Why not write a plugin and bind it to validate?

  • You want to automatically reformat your code anytime you compile? Why not write plugin and bind it to process-sources?

  • You want to check the unit-test coverage of the project and ensure it is always high enough? Write a plugin and bind it to the verify phase.

Now, you could say that sometimes you want to execute a plugin, but not as part of any phase. So this can feel a bit coercive.

Good news: you can do that at anytime with mvn <plugin>:<goal>.

For example, run mvn jar:jar and maven will only execute that binding. This can be useful if you have a plugin that lets you refactor your code according to a given rule, or just do any one-off thing.

6. Is that it?

Now, it would be nice if you could see all those phases and their bindings, and turns out you can!

For example: mvn help:describe -Dcmd=clean (replace clean by any other phase):

[INFO] 'clean' is a phase within the 'clean' lifecycle, which has the following phases:
* pre-clean: Not defined
* clean: org.apache.maven.plugins:maven-clean-plugin:2.5:clean
* post-clean: Not defined