How to Build a Java Maven Project

Why Apache Maven?

Apache Maven allow you to easily build, manage, test, and run your Java projects without having to spend time troubling with semantics. You want to focus on creating quality for your product and not on how to structure or which libraries should you include or not include. Maven is a project management and build automation tool that gives developers control over the entire project lifecycle. Project teams can easily collaborate since Maven uses a standard structure and easily integrates automated building tools. It is similar to Ant in that it simplifies building but is more complex with more capabilities. 

The key features that Maven offers are simple project setup, uniform structure across all subproject, built-in dependency management and updating, dynamic downloading of external plugins and libraries, website and documentation generation, and backwards compatibility with older Maven versions. We will get into all these details as we create our first Maven project here.

This guide will get you started with Maven in under 15 minutes! So let’s begin.

Install Maven

First, since Maven is a Java tool, you must have Java installed on your machine. After installing Java, download Maven and follow the install instructions. After that, type this command to verify your download and check version.

mvn --version

If Maven installed correctly, you should see something like:

Maven home: /Users/thomas.fitzgerald/apache_maven_3.5.2/apache-maven-3.5.2
Java version: 1.8.0_211, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.15.4", arch: "x86_64", family: “mac"

If you did not see similar output to the above, then you need to configure Maven additionally. Windows users may require to add Maven and Java to their operating system Path, done here

Create a Project

Another amazing feature of Maven is the ability to store and load remote artifacts using its native archetype. We will get into creating your own Maven archetype in later modules, but let’s generate Apache Maven’s Quickstart archetype. The beauty of Maven is that you don’t have to get sidetracked making sure you create the proper structure. You can generate a remote archetype directory and modify its boilerplate to suite your project’s needs. 

First, create a directory anywhere on your machine. Let’s call this directory “maven quickstart”. Change directory into your new maven_quickstart and from shell, execute this command to generate your Maven project:

mvn archetype:generate -DgroupId=my.first.app -DartifactId=quick-start-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

In the above command, the groupId is the id of your group’s project and artifactId is the id of your project’s artifact, or deployment object. Your artifactId is also the top level directory name of your project. This will probably take a long time since this command installs the most recent jars and plugins to your local environment. It is possible that the remote server the artifacts are being downloaded from times out, so you may have to execute this command again if so. 

Inspect Project Structure

Change directory into quickstart-app. Notice how your project structure looks like below:

pom.xml
src
    main
        java
            my
                first
                    app
                        App.java
    test
        java
            my
                first
                    app
                        AppTest.java

The src/main/java directory contains source code, and the src/test/java contains your unit testing. The pom.xml is the core of your project. It is a configuration file that contains all of your project’s information needed to build, test, and deploy. The pom.xml can seem intimidating but it’s main point is to define the structure for creating and using your project’s artifacts. 

Project POM

Let’s have a look at it below, minus its dependencies for better clarity: 

<?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>my.first.app</groupId>
  <artifactId>quick-start-app</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>quick-start-app</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>
<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  </project>

The main information to take from our pom.xml is:

  • project root
  • modelVersion – should be set to 4.0.0
  • groupId – the id of the project’s group.
  • artifactId – the id of the artifact (project)
  • version – the version of the artifact under the specified group

The groupId, artifactId, and version all must be here to configure our package. These combined properties give us our project’s fully qualified name. The fully qualified name here is groupId:artifactId:version, or my.first.app:quick-start-app:1.0-SNAPSHOT. These are just the required basic properties. Other properties, like dependencies, packaging type, or plugins will be inherited from the Maven’s default POM if not defined. 

Build Our Project

Execute the following command:

mvn package

You should see a lot of output ending with:

[INFO] -----------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------------------
[INFO] Total time: 3.994 s
[INFO] Finished at: 2020-05-06T00:29:37-04:00
[INFO] Final Memory: 20M/212M
[INFO] -----------------------------------------------------------------------

This command only executed one phase in the Maven build cycle. This just compiled and packaged our pom.xml’s package type into a .jar file located in our project’s target/ folder. The default package type of a POM is a jar, this goes along with what I talked about in the last chapter. You can change directory into target/ and find the jar. 

d target/
Thomass-MacBook-Pro:target thomas.fitzgerlad$ ll
-rw-r--r--   1 thomas.fitzgerlad  staff  2748 May  6 00:29 quick-start-app-1.0-SNAPSHOT.jar

Compile and Run Our Project 

Now that we have built our jar, we can compile and run our first app! Use the below command to run your jar and get our output:

java -cp quick-start-app-1.0-SNAPSHOT.jar my.first.app.App

You should see the following output to your shell:

Hello World!

Wrap Up

Done!

We have just seen how a simple Maven project is structured and learned some information about its properties. We also found that we can use already existing Maven remote projects to build our own custom project. You can play around with the pom.xml, add more source and test files, and even add sub-projects if you like. Next module will talk about how to create your own archetype to create your own custom prototype.