Due to my Android development background, I am more used to Gradle than to Maven. Although I knew that Gradle was based on Maven, I had never investigated what was going on behind the scenes. During the last week, I have been trying to understand the details and find out what are the different Maven's components.
What is Maven
Maven is a build and dependencies management system used primarily for Java projects.
Key features include:
- Create new projects through archetypes.
- Project configuration in POM file and Settings file
- Project building using lifecycles, phases, plugins, goals and build profiles.
- Dependency management through repositories
- Deployment with the release plugin.
The Project Object Model
The Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file, usually defined in the project root directory, that contains information about the project and the configuration used by Maven to build the project.
The configuration that can be included in the POM file is as follows:
- Plugins and goals
- Build profiles
- Project metadata such as version, description, developers, etc.
To facilitate a default configuration for all project, Maven provides what is known as the Super POM. The Super POM is Maven's default POM. All POMs extend the Super Pom thus inheriting the configuration specified in the Super POM.
The Settings File
As mentioned above, the POM file contains the project configuration, whilst the Settings file contains the user specific configuration. There can be two settings files, the Global settings file, situated in the Maven install directory, and the user's settings file that is situated in the user's home directory.
The settings file can provide the following configuration:
Maven build process is based on lifecycles. The lifecycle provides a clearly defined process for building and distributing project artifacts.
There are three different lifecycles in Maven.
- Default: Handles project building and deployment.
- Clean: Handles project cleaning.
- Site: Handles project's site docs.
Each lifecycle is defined by a series of stages named build phases. A build phase is responsible for a specific step in the lifecycle, but the way it carries out its duty depend on the plugin goals bound to the phase.
Plugins are artifacts that provide goals for the build phases. Dividing the phases into goals, provided by plugins, make the build process really flexible and customizable.
A plugin can provide one or more goals. Each goal represents a capability of that plugin.
For example, Maven only supports a single source and test directories for a project. If we decided to add additional directories to the project, we could use a plugin that provides goals to add source and test directories to the build process.
Goals are responsible for executing specific tasks during each phase.
Some phases have default goals. For the default lifecycle, default goals are provided by the packaging option, defined in the project's POM file.
In addition to the default goals, extra goals can be defined by configuring plugins in the project's POM file. Therefore, a particular build phase can be composed of multiple goals. If a phase does not have any goals, it won't be executed as part of the lifecycle.
Most of the plugins provide goals that are bound to build phases. However, there are some plugins that provide goals which are meant to be executed separately, not as part of the build lifecycle.
The Archetype Plugin
If you happen to be an IntelliJ user, you may have seen that when creating a new Maven project the first option is a list of archetypes. Have you ever wonder what is it for? I have to say that I did not until I found what archetypes are by digging into Maven features.
An archetype is simply an existing project template. The Archetype plugin provides Maven project templates. It creates the project structure and POM file based on standard templates. The process of creating a new project is done in an interactive way by just providing project specific configuration such as groupid, artifact name, etc.
It helps to apply project or organisation's best practices. New users can have, in seconds, a working project to use as a walking skeleton.
The plugin has additive support, meaning that can be used to add pieces to existing projects, i.e. Maven site archetype can quickly create a documentation site for the project.
Users can create their own archertypes in their organisation's repository and use them as a base for new projects.
Being a standalone plugin, the archetype plugin provides goals that are not bound to any lifecycle. The goals are executed directly, as opposed to what is done when using the lifecycle, where goals are executed as part of the lifecycle phases.
Provide a standard mechanism to release project artifacts.
The Release plugin has two main goals.
- Verify there are not uncommitted changes.
- Prompt user to provide a tag, release, and development version names.
- Modify and commit release info in the POM file.
- Tag entire project.
- Extract file revisions under new tag name
- Execute the Maven lifecycle on the extracted project instance
- Deploy the artifacts to local and remote repositories
Maven uses repositories to hold build artifacts and dependencies.
Maven Repositories are used as in Git, but storing build and dependencies artifacts instead of source code. Doing so, users can easily consume your project artifacts from the repositories.
There are two types of repositories
remote, both are structured the same way. The local repositories live in the users' local machines and are used as a cache of the remote repositories, providing offline building capabilities. The remote repository can be divided into two subgroups,
internal. Public repositories hold artifacts that are publicly available, whilst internal repositories are created in organisations to share internal artifacts between development teams.
It's strongly recommended that when using maven, dependencies JARs are not stored in source control, but in the repositories. Doing so, Maven is able to handle transitive dependencies, as all dependencies information is available through the POM file and the Maven repositories.
Maven Build Profiles are used to facilitate portable builds. The build profiles modify the POM file at build time to provide equivalent-but-difference parameters that are environment dependent. For example, it is the perfect place to define filesystem references that are different for each user.
Profiles provide properties that can be referenced in the POM file. The properties are defined in the
<properties> section in the profile declaration.
Build profiles can be declared in the POM file, as a per project definition, or in the Settings files. Build profiles defined in the Global Settings file are available for all users of the machine, whilst the ones defined in the User Settings file are available only for a particular user.
Profiles are triggered in different ways:
- Explicitly: Running a Maven build through the command line, including -P option.
- Maven settings: Including the profile in the
<active profiles>section. When using this option the profile is always active.
<activation>section in profile declaration: The activation section can activate a certain profile based on environment variables, OS settings, and missing or present files.
There are many areas where Maven can ease development effort:
- Easy build process
- Uniform build system
- Rich project information
- Guidelines for best development
- Transparent migration to new features
I realised how many Maven features I was not aware of until recently, and I invite you to check them yourself. You will not be disappointed.