Lesson 1: The POM File

1. Overview

The goal of this lesson is to introduce the Maven POM file. The POM (Project Object Model) file is the central resource for configuring a Maven project. In this lesson, we'll learn the basics of the POM file and begin to migrate our sample project to using Maven.

The relevant module we need to import when we're starting with this lesson is: the-pom-file-start

If we want to have a look at the fully implemented lesson as a reference, feel free to import: the-pom-file-end

2. About the POM File

The POM file is a single XML file that lives in the top-level directory of a Java project. The POM file, named pom.xml, defines every aspect of our project including the Java version, dependencies, plugins, and much more.

3. Minimal POM Example

Therefore, let's go to the root directory of our project, and create a pom.xml file that will contain the simplest possible definition:

Every POM file starts with <project> as the top-level element. We also include some XML namespace declarations, followed by the model version and the coordinates of the project. The model version indicates which version of the POM specification our project conforms to. In this case, 4.0.0 is the most recent available, but is subject to change in future versions of Maven.

The project coordinates specify a unique way to identify this project. This is a very important concept in Maven which we will explore in the next section.

4. Project Coordinates

Project coordinates provide a unique way to identify a software library or application. They consist of three components - group, artifact, and version. Each of these serves a distinct purpose for identifying a software project:

  • group: identifies the organization that created or maintains the project. Most projects within the same organization will use the same group ID for each project, although this isn't a requirement. The group also usually aligns with the top-level Java package name within the source code of the project, but again this isn't a requirement.
  • artifact: a descriptive name of the library or application.
  • version: used to identify unique incarnations of a project over time. While this is typically typically follows semantic versioning, it doesn't have to.

When specified together, project coordinates are usually appended into a single string separated by the colon character. For example, the full coordinates of our example project are com.baeldung.lm:learnmavem:1.0.0. For this reason, we should avoid using the colon character in both the group and artifact components.

5. Adding a Library Dependency

In a Maven project, the external libraries our project needs to compile or run are called dependencies. We’ll go into these in detail in a future lesson.

But, for now, let’s see a basic example of what this would look like, by adding a Spring Boot web library to our project:

We first added a parent <dependencies> element to our pom.xml file, then introduced our web library using a <dependency> element. This includes the 3 project coordinates we discussed:

  • group: org.springframework.boot
  • artifact: spring-boot-starter-web
  • version: 3.2.2

Based on these attributes, Maven will identify the correct library (artifact) from a pre-defined repository and download it for us. This means we don’t have to manually download and add the JAR file to the project.

6. Default Directory Structure

Maven defines a default directory structure that it expects our files to be in. Let's take a closer look at the directory structure now.

To start, all of the source components lives under the same parent directory named src. From there, Maven expects two sub-directories named main and test. And at a third level, we'll have java and resources, to contain the actual Java-based source code and the additional non-code files, as we can imagine.

Finally, Maven uses a single top-level directory named target for all build output. This includes .class files, .jar files, and anything else our project dynamically generates during the build and test phases. Using this single directory for all dynamic files has two benefits:

  • We only need a single .gitignore instruction to prevent the accidental merging of dynamic files.
  • Cleaning our project is as simple as removing one directory.

In the end, our project will have a directory structure that looks like this:

Let's now re-arrange our project elements following this arrangement:

  • We'll have to move the content of the current src directory to src/main/java
  • From resources to src/main/resources
  • The test-src elements to src/test/java
  • We can simply remove the libs, outtest-libs, and test-out directories since these are all things that Maven will handle for us

This is the first step towards building our project with Maven. Note that at this point, our POM file is still missing some important definitions and thus we won't be able to build the project just yet. For example, we still need to add some missing dependencies. We will cover these aspects in the next lessons.

Complete and Continue