Maven (Part 2) - Your First Maven Project
Maven (Part 2) - Your First Maven Project

Maven (Part 2) - Your First Maven Project

in
  1. Your First Maven Project
  2. compile: Compiling Application Source
  3. test: Compiling Test Source and Running Unit Tests
  4. package and install
  5. site and clean

Your First Maven Project

Let’s dive right into creating your first Maven project! To create our first Maven project, we’ll employ Maven’s archetype mechanism. Archetypes are defined as original patterns or models from which all other similar things are made. In Maven, an archetype is a project template that, combined with some user input, generates a working Maven project tailored to the user’s needs. We’ll show you how the archetype mechanism works, but if you want to delve deeper into archetypes, check out our Introduction to Archetypes.

Let’s kickstart your first project! To create the simplest Maven project, execute the following command from the command line:

mvn -B archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

After executing this command, you’ll notice some action taking place. Firstly, you’ll observe a directory named my-app being created, containing a file named pom.xml, which should look like 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
 
  <name>my-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>
 
  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
       ... lots of helpful plugins
    </pluginManagement>
  </build>
</project>

The pom.xml contains the Project Object Model (POM) for the project. The POM is the fundamental working unit in Maven. Remember this, as Maven is fundamentally project-centric, and everything revolves around the concept of a project. In essence, the POM contains every crucial piece of information about your project and is essentially a one-stop shop for finding anything related to your project. Understanding the POM is crucial, and new users are encouraged to refer to the POM Introduction.

This is a very basic POM, but it still showcases key elements present in every POM, so let’s go through them one by one to acquaint you with the essentials of POM:

  • project: This is the top-level element in all Maven pom.xml files.
  • modelVersion: This element indicates the version of the object model that the POM is using. Changes to the model itself are rare, but when Maven developers deem it necessary to alter the model, it’s mandatory for ensuring stability.
  • groupId: This element indicates the unique identifier of the organization or group that created the project. The groupId is one of the key identifiers for a project, usually based on the organization’s fully qualified domain name. For example, org.apache.maven.plugins specifies the groupId for all Maven plugins.
  • artifactId: This element indicates the unique base name of the primary artifact generated by this project. The primary artifact of a project is typically a JAR file. Secondary artifacts like source bundles also use the artifactId as part of their final name. The typical format for Maven-generated artifacts is <artifactId>-<version>.<extension> (e.g., myapp-1.0.jar).
  • version: This element indicates the version of the artifact generated by the project. Maven assists you significantly in version management, and you often see the SNAPSHOT indicator in versions, denoting that the project is in a developmental state. We’ll discuss the use of snapshots and how they further work in this guide.
  • name: This element indicates the display name for the project. This is frequently used in Maven-generated documentation.
  • url: This element indicates the location where the project’s site can be found. This is frequently used in Maven-generated documentation.
  • properties: This element contains placeholders for values accessible throughout the POM.
  • dependencies: This element’s children list the dependencies of the POM. The cornerstone of the POM.
  • build: This element deals with things like declaring the project’s directory structure and managing plugins.

For a complete reference of elements you can use in the POM, refer to our POM Reference. Now let’s get back to our project at hand.

Upon generating the prototype for the first project, you’ll also notice the following directory structure created:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

As you can see, the project created from the archetype has a POM, a tree for your application source, and another for your test source. This is the standard layout for a Maven project (application source resides in ${project.basedir}/src/main/java, and test source resides in ${project.basedir}/src/test/java, where ${project.basedir} denotes the directory containing the `pom

.xml` file).

This is the directory structure we recommend using if you’re manually creating a Maven project. It’s a Maven convention, and to learn more, you can read our Introduction to the Standard Directory Layout.

Now that we have the POM, application source, and test source, let’s see how to compile them.

compile: Compiling Application Source

Navigate to the directory containing pom.xml and execute the following command to compile the application source:

mvn compile

After executing this command, you’ll see the following output:

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to <dir>/my-app/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.899 s
[INFO] Finished at: 2020-07-12T11:31:54+01:00
[INFO] ------------------------------------------------------------------------

Upon compiling for the first time (or any command for that matter), Maven will need to download all plugins and dependencies necessary to fulfill that command. From a fresh Maven installation, this might take quite some time (in the output above, it took almost 4 minutes). Upon subsequent executions of the command, Maven now possesses what it needs, so it doesn’t need to download anything new, making the command execution faster.

From the output, you can see that the compiled classes are placed in ${project.basedir}/target/classes, which is another standard convention used by Maven.

test: Compiling Test Source and Running Unit Tests

Now that you’ve successfully compiled the application’s source code, and now that you have some unit tests you want to compile and execute (because every programmer always writes and runs their unit tests), execute the following command:

mvn test

After executing this command, you should see the following output:

......
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.881 s
[INFO] Finished at: 2020-07-12T12:00:33+01:00
[INFO] ------------------------------------------------------------------------

Some points to note about the output:

  • Maven this time downloaded more dependencies. These are dependencies and plugins necessary for executing tests (it already had dependencies needed for compilation and didn’t download them again).
  • Before compiling and executing tests, Maven compiles the main code (all these classes are up to date since we haven’t changed anything since the last compilation).

If you only want to compile the test source (but not execute tests), you can execute the following command:

mvn test-compile

Now you can compile the application source code, compile tests, and execute tests.

Note that the Surefire plugin (for executing tests) looks for tests contained within files with specific naming conventions. By default, included tests are:

  • **/*Test.java
  • **/Test*.java
  • **/*TestCase.java

Default exclusions are:

  • **/Abstract*Test.java
  • **/Abstract*TestCase.java

package and install

Creating a JAR file is as simple as executing the following command:

mvn package

Now, you can check the ${project.basedir}/target directory, where you’ll find the generated JAR file.

However, we also need to install the generated artifact (JAR file) in the local repository (${user.home}/.m2/repository is the default location). For more information on repositories, you can refer to our Repository Introduction, but let’s proceed to install our artifact! To do so, execute the following command:

mvn install

After executing this command, you should see the following output:

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ my-app ---
[INFO] Installing <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar to <local-repository>/com/mycompany/app

/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar
[INFO] Installing <dir>/my-app/pom.xml to <local-repository>/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.678 s
[INFO] Finished at: 2020-07-12T12:04:45+01:00
[INFO] ------------------------------------------------------------------------

You have now completed the process of setting up, building, testing, packaging, and installing a typical Maven project. This is likely what the majority of projects will use Maven for, and if you’ve noticed, everything you’ve been able to do so far is driven by an 18-line file (the project’s model or POM).

site and clean

Maven offers more functionalities without needing any additions to the current POM.

mvn site is one of Maven’s highly praised functionalities. With no extra work, this POM has enough information to generate a website for your project! You’ll likely want to customize your Maven site, but if you’re in a hurry, executing that command will provide basic information about your project.

mvn clean removes the target directory containing all the build data, leaving it clean.