mvn clean install - a short guide to Maven - header image

mvn clean install - a short guide to Maven

Last updated on October 17, 2020 -
Star me on GitHub →  

You can use this guide to understand what a 'mvn clean install' really does. Also: A crash-course on Maven and workarounds for its most common pitfalls.

What does mvn clean install do?

The short answer

Apache Maven is a popular build tool, that takes your project’s Java source code, compiles it, tests it and converts it into an executable Java program: either a .jar or a .war file.

mvn clean install is the command to do just that.

  1. You are calling the mvn executable, which means you need Maven installed on your machine. (see How do you install Maven?)

  2. You are using the clean command, which will delete all previously compiled Java .class files and resources (like .properties) in your project. Your build will start from a clean slate.

  3. Install will then compile, test & package your Java project and even install/copy your built .jar/.war file into your local Maven repository. (see A look at the Maven build lifecycle: phases)

The (short) long answer:

There is more to Maven than a couple lines on 'mvn clean install'. If you want to learn about how Maven’s dependency management and build cycle works, or how to avoid the most common pitfalls when working with it: Read on.

Maven: Crash-Course

Maven is one of the most popular build tools in the Java universe (others being Gradle or old-school Ant). You can not only build Java projects with it, but pretty much every project written in a JVM language like Kotlin or Scala, as well as other languages like C# and Ruby.

Now what exactly does a build tool do? Maven does three things rather well:

  1. Dependency Management: Maven lets you easily include 3rd party dependencies (think libraries/frameworks such as Spring) in your project. An equivalent in other languages would be Javascript’s npm, Ruby’s gems or PHP’s composer.

  2. Compilation through convention: In theory you could compile big Java projects with a ton of classes, by hand with the javac command line compiler (or automate that with a bash script). This does however only work for toy projects. Maven expects a certain directory structure for your Java source code to live in and when you later do a mvn clean install , the whole compilation and packaging work will be done for you.

  3. Everything Java: Maven can also run code quality checks, execute test cases and even deploy applications to remote servers, through plugins. Pretty much every possible task you can think of.

Maven’s directory layout

Maven’s pom.xml

Technically, any directory that contains a pom.xml file is also a valid Maven project. A pom.xml file contains everything needed to describe your Java project. Let’s have a look at a minimal version:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.marcobehler</groupId>
    <artifactId>my-project</artifactId> (1)
    <version>1.0-SNAPSHOT</version> (2)

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source> (3)
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency> (4)
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
  1. We are defining a project called 'my-project'

  2. With a version number of 1.0-SNAPSHOT, i.e. work-in-progress

  3. Using Java 1.8 for compilation

  4. With one dependency needed for unit testing: junit in version 4.12

Maven’s src & target folders

Apart from a pom.xml file, you also need Java source code for Maven to do its magic, whenever you are calling mvn clean install. By convention:

  • Java source code is to be meant to live in the "/src/main/java" folder

  • Maven will put compiled Java classes into the "target/classes" folder

  • Maven will also build a .jar or .war file, depending on your project, that lives in the "target" folder.

In the end, your project will look like this:

+ myproject
    + -- src
        + -- main
            + -- java
                 MyApp.java
    + -- target
        + -- classes (after 'mvn compile')
             MyApp.class

        myproject.jar (upon mvn package or mvn install)

    pom.xml

Now that you have a pom.xml file, as well as a src folder, you still need Maven installed on your machine. Let’s do that now.

How do you install Maven?

Installing Maven is rather simple. Similar to Java it is just a .zip file that you need to download and put anywhere on your harddrive. The .zip file’s contents look like this:


Directory c:\dev\apache-maven-3.6.3

12.07.2019  09:25    <DIR>          .
12.07.2019  09:25    <DIR>          ..
12.07.2019  09:25    <DIR>          bin
12.07.2019  09:25    <DIR>          boot
12.07.2019  09:25    <DIR>          conf
12.07.2019  09:25    <DIR>          lib
12.07.2019  09:24            13.437 LICENSE
12.07.2019  09:24               182 NOTICE
12.07.2019  09:24             2.533 README.txt

Now you need to make sure to add the /bin directory to your PATH variable, otherwise you cannot call 'mvn' (think: mvn clean install) from anywhere. That’s it.

If you are unsure about any of these two steps, there’s a great video on Youtube, showing how to install the latest Maven 3.6 on Windows.

A look at the Maven build lifecycle: phases

Now what really happens when you execute a mvn clean install in your project? Maven has the concept of a build lifecycle, which is made up of different phases.

Here’s what Maven’s default lifecycle looks like (note: it is missing 'clean').

mavenphasesv3

These phases are sequential and depend on each other.

Example:

When you call mvn deploy, mvn will also execute every lifecycle phase before deploy, in order: validate, compile, test, package, verify, install.

Same for verify: validate, compile, test, package. Same for all other phases.

And as clean is not part of Maven’s default lifecycle, you end up with commands like mvn clean install or mvn clean package. Install or package will trigger all preceding phases, but you need to specify clean in addition.

Where does Maven store 3rd party libraries?

Contrary to other languages, where project dependencies are stored in your project’s directory, Maven has the concept of repositories.

There are local repositories (in your user’s home directory: ~/.m2/) and remote repositories. Remote repositories could be internal, company-wide repositories like Artifactory or Nexus or the (reference) global repo at https://repo.maven.apache.org/maven2/.

Maven will always download your project dependencies into your local maven repository first and then reference them for your build. When you think back at your pom.xml file from before:

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

Then mvn will, once you try and "mvn test" your project, download the junit dependency into ~/.m2/repository/junit/junit/4.12/junit-4.12.jar and reference it via Java’s classpath mechanism for your build.

For more info on using repositories, see the official documentation at https://maven.apache.org/guides/introduction/introduction-to-repositories.html.

Common Maven Questions

Where can I find the Maven coordinates for any 3rd party library?

Popular sites are https://mvnrepository.com/ or https://search.maven.org/. You can find others in this thread on Stackoverflow.

What is the difference between mvn clean package and mvn clean install?

If you followed the guide, this should be pretty much clear by now.

  • clean: deletes the /target folder. So, the same result for both commands.

  • package: Converts your .java source code into a .jar/.war file and puts it into the /target folder.

  • install: First, it does a package(!). Then it takes that .jar/.war file and puts it into your local Maven repository, which lives in ~/.m2/repository.

Why do I need to call clean at all? Wouldn’t mvn install be enough?

In theory, calling mvn install would be enough if Maven was smart enough to do reliable, incremental builds. That means figuring out what Java source files/modules changed and only compile those.

In practice, it is actually enough for the vast majority of cases, but note: Before Maven 3.1 incremental compilation was basically non-existent, and even with the latest Maven and compiler plugin versions there’s the odd bugs and documentation issues in the incremental compilation support.

Hence developers got it ingrained to always call 'mvn clean install', even though this increases build time a lot in bigger projects.

Why does mvn clean install not build sibling projects?

Unfortunately, this is something that happens in multi-module projects and other build tools like e.g. Gradle have no problem with it. Imagine your Maven build looks like this:

+ stocks-broker-app (parent)
    + stocks-data-module
    + stocks-rest-module (depends on stock-data)
    + stocks-ui-module (depends on stock-data)

and you are doing the following:

cd stocks-ui-module
mvn clean install  // or another appropriate goal

The problem is: Maven will NOT be smart enough to automatically build stock-data as a needed sibling dependency. Instead, you will need to have stock-data built already, yourself.

There’s a workaround though. You don’t always have to build the whole parent project, instead you can specify the list of submodules to build and do a dependent build. In our case, this would look like:

cd ..  // so you are in the parent project
mvn -pl stocks-ui-module -am clean install  // or another appropriate goal
  • -pl lets you specify the submodules to build

  • -am stands for also make, which will build dependent modules as well

What does mvn -U do?

Sometimes, if your project depends on SNAPSHOT dependencies, Maven will not update your local Maven repository with the very latest snapshot version.

This is a bit oversimplified, but if you want to make sure that Maven always tries to download the latest snapshot dependency versions, invoke it with the -U switch.

mvn -U clean install

What is mvnw?

Some projects come with a mvnw executable, which does not stand for Maven (on) Windows, but rather for Maven wrapper.

This means you don’t have to have mvn installed on your machine to build your project - rather, mvn is embedded in your project directory and you can call it with the mvnw executable.

Learn more about the Maven wrapper here.

Fin

This guide is just a quick overview of what Maven can do for you and how to work around its most common pitfalls.

If you have any comments or feedback, or want to suggest a another common Maven question, simply leave a comment below.

Thanks for reading.

There's more where that came from

I'll send you an update when I publish new guides. Absolutely no spam, ever. Unsubscribe anytime.


Share

Comments

let mut author = ?

I'm @MarcoBehler and I share everything I know about making awesome software through my guides, screencasts, talks and courses.

Follow me on Twitter to find out what I'm currently working on.