Apache - Maven - What is Maven?

Maven is a tool, mainly developed for Java developments.
This is a complete software so it is not so easy to understand when you start developing, even with the official website of Maven: http://maven.apache.org/.

But I will try to reduce the explanation of what is Maven with some examples.

You can start by following this tiny installation tutorial of Maven for Windows.

OK, let's see in details what Maven is.
First of all, every project with Maven has a pom.xml file.
POM means Project Object Model.
With this XML file, a team manager can configure a project and how Maven will interact with this project.
It means that if a project contains subprojects, we will have more than one pom.xml.
In fact, one for each project.
The POM into sub projects will inherite from the Super POM and so on for others child projects.

There is also a settings.xml that allows people to work on a same project without the same configuration as others.
This settings.xml file is unique for each developer and depends of the system of each developer.

For example a developer can work on Mac OS, another on Linux, one else on UNIX, and some on Windows XP, Windows Vista and Windows 7.
And each developer works on a different IDE, such as Eclipse, NetBeans, IntellJ IDEA, etc.
But all these people are working on the same project.

Do you think it is impossible?
Even if it is not very common, Maven will help us for that!

But before seeing it, let's see some useful tips.

All following tips are a default configuration of Maven and of course, you can change all of them.
But you have to know that the default configuration contains a lots of conventions used by others developer teams.
So it is a good practise to use the default configuration of Maven.
Think convention over configuration.

The .m2 directory

Maven will download all files needed from Internet into a directory named .m2.
On Window 7, this folder will be created in this location: C:\Users\.m2.
These files are binaries and projects built.

Why this name .m2?
The m2 stands for Maven 2.
It was not changed for the version 3 of Maven.

Maven will create another directory inside this .m2, named repository.
So once Maven will be launched for the first time, all files will be stocked in C:\Users\.m2\repository.

So open a command prompt and write the three letters mvn (mvn standing for Maven of course):

$ mvn

A lots of errors will occur.
This is normal.
But you can see that the repository directory has been created but whitout any file inside.

Let's now create a project with Maven.

Creating a project with Maven

To execute Maven, we need a pom.xml.
But we don't have one.
No problem, for this first execution we will use another way to create a project.

We will assume the following directory as our development directory: C:\www\java\maven-testing.
Go in this directory and open a command line tool, such as cmd, MinGW or Cygwin.
To be honest the cmd of Windows is enough (WinKey + R, then write cmd).

Plugins, goals and artifacts

This chapter may seem complicated, to be honest it is, so don't be afraid if you do not understand at all the first time you will read it.
I will give you a final command to create our first project with Maven.
It will be more clear for you (I hope so).

When you want to use plugins by calling the mvn command, Maven needs at least a plugin and each plugin needs one goal.

To use a plugin with Maven, we must have the following syntax:

$ mvn plugin:goal

In the following example, archetype is the plugin and generate is its goal.

$ mvn archetype:generate

Archetype is a plugin to create templates of our choice (you can even create yours).
Generate is the goal that the plugin (Archetype) will use.

But the plugin Archetype needs also an ArtifactId.
It's easy to confound Archetype and Artifact, the name are almost the same.
Actually these two nouns are completely different.

Indeed in Maven, an artifact is almost synonym of a project.
So when we say ArtifactId it is like ProjectId.
With this ArtifactId, Maven will know which template generate.
We can add it among an official list that you can find on the Maven's website.

In our example, we will use the ArtifactId: maven-archetype-quickstart.
This ArtifactId will generate a project with a simple template.

So in our example, Maven needs a plugin.
This plugin needs a goal.
This goal needs an ArtifactId to know which sort of project generate.

mvn > plugin > goal > pluginArtifactId

But to use the plugin Archetype, we must configure it before.
For that, we just have to specify the GroupId and the ArtifactId of the project.
All projects and plugins have an ArtifactId, most of time different.

As we don't have any POM and even any project, we will generate all that with a command line.
Notice that a command line will always override the code inside the POM.
Let's set the properties of our project.

The GroupId of the project is a sort of package and for our example it will be: com.badprog.
The ArtifactId  is the name of our project, in our case: tuto1.
We have also to specify a version of the project, for example: 1.0.

But by default the value of the version is 1.0-SNAPSHOT.
We want to follow conventions of Maven, so we will keep this value and skip the version parameter, for that we will deactivate the InteractiveMode in the command.

Here we are, let's have a look to the final command and execute it in our development directory:

$ mvn archetype:generate -DgroupId=com.badprog -DartifactId=tuto1 -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Notice that it is one single line.
Each property begins by the prefix -D.

It will generate a new project named tuto1.

Inside we have a src directory and the famous pom.xml file.
Open the POM file and you will see this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.badprog</groupId>
  <artifactId>tuto1</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>tuto1</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

We can find in the POM some parameters we have typed in the command, like:

  • <groupId>com.badprog
  • <artifactId>tuto1

Of course all of them could have been set by us.
We can also see the dependency JUnit, auto-generated by Maven.
This is not the last release version of JUnit, but we can easily modify it.

Two other files has been generated:

  • C:\www\java\maven-testing\tuto1\src\main\java\com\badprog\App.java
  • C:\www\java\maven-testing\tuto1\src\test\java\com\badprog\AppTest.java

You can't think Maven without thinking Unit testing.
We will see this later.
You can of course see the source code of your App.java and AppTest.java files.

We have now a project and even a pom.xml file.
We can then talk about the build lifecycle and phases that Maven uses.

Build, lifecycle and phases

There are three default lifecycles used by Maven:

  • clean
  • default
  • site

Each lifecycle is divided into phases.

For example, the clean build lifecycle is composed of eight phases:

  1. validate
  2. compile
  3. test
  4. package
  5. integration-test
  6. verify
  7. install
  8. deploy

Every phase needs its precedent one.
It means that if you type this:

$ mvn package

Before executing the package phase, Maven will perform validate, compile, test and package phases.
It is then equal to:

$ mvn validate
$ mvn compile
$ mvn test
$ mvn package

So if you type:

$ mvn deploy

The entire default build lifecycle will be executed.

But if you type this last phase, deploy, you will have a beautiful error:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.5:deploy (default-deploy) on project tuto1: Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help 1]

Why?
Because the pom.xml doesn't know where to deploy the .JAR generated.

Yet, for the moment we can execute the install phase because we do not need any more configuration to be performed.
So let's type it:

$ mvn install

We can see a new directory created: target.
In C:\www\java\maven-testing\tuto1\target, we can see the our project packaged with the correct extension we specified in the pom.xml: tuto1-1.0-SNAPSHOT.jar.

We can execute it directly, from the C:\www\java\maven-testing\tuto1 directory, with the following command:

$ java -cp .\target\tuto1-1.0-SNAPSHOT.jar com.badprog.App

Of course, the -cp command stands for -classpath.
The result:

Hello World!

The .JAR is then valid.
If you don't know why this sentence appears, it is because the class App.java we generated with Maven contained it.

The famous pom.xml

A Maven project doesn't need code outside the POM.
It means that you can drive your project directly from this file.

Unlike a procedural build.xml, for an Ant task, the pom.xml is declarative.
It means that before compiling anything, Maven will see which informations of the POM are valid and which are not.
If all is OK, it will launch the build lifecycle.

Every POM has at least three tags (if we don't count <project> and <modelVersion>):

<groupId>com.badprog</groupId>
<artifactId>tuto1</artifactId>
<version>1.0-SNAPSHOT</version>

Easy to understand:

  • GroupId is filled by the organization or the company domain.
  • ArtifcatId is filled by the name of the project.
  • Version is filled by the version of the current project.

So Maven is now sure, thanks to the POM, which version of the project and of the organization build.

But of course, to have a better using of the POM, we can have more useful tags.

Dependencies

Each dependency has a specific tag <dependency>.
And each <dependency> tag is included inside a <dependencies> tag.
We have then something like that:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.0</version>
      <type>jar</type>
      <scope>test</scope>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
  ...
</project>

Maven will download all dependencies specified in your POM and all dependencies dependent on other dependencies.
It means that if Maven need a dependency not specified in the POM to execute a dependency specified in the POM, it will download it.

But there is a problem, a project may have a specific .JAR needed but with a licence that forbids to being in a central repository (free to download from any Internet website).
And as every problem has a solution, there is of course one for this case.
Indeed, we have to create our own repository to allow developers of our team to download these files directly from Maven.

It was an explanation of Maven and I hope it helped you to understand what is Maven. cool

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.