Baeldung

Java, Spring and Web Development tutorials

 

What’s New in Maven 4
2025-12-22 05:01 UTC by Ralf Ueberfuhr

1. Overview

Maven has powered the Java build ecosystem for nearly two decades. Maven 3 appeared in 2010, and the community has awaited a major update since. Now, Maven 4 brings better performance, clearer model semantics, improved extensibility, and modern dependency resolution.

In this article, we explore the key changes in Maven 4. We show new features and provide code samples. We can find more details in the Maven Documentation.

In this article, we rely on Maven 4 RC5 as our reference version. At the time of writing, the Apache Maven project has not announced a final GA release date for Maven 4. Because of that, we base all examples and explanations on the most recent release candidate available. We need to declare the 4.x beta versions of the default plugins (esp. maven-compiler-plugin, maven-install-plugin, and maven-deploy-plugin) explicitly, because the RC does not provide them as default versions.

2. Model Version 4.1.0

Maven 4 updates the POM version to 4.1.0. It is compatible with version 4.0.0, but adds elements and marks some elements as deprecated.

The POM now looks like this:

<project
    xmlns="http://maven.apache.org/POM/4.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd">
  <modelVersion>4.1.0</modelVersion>
  <!-- ... -->
</project>

We could omit the modelVersion element since Maven derives it from the schema.

Updating existing projects is optional. Maven 4 can build projects with version 4.0.0 or 4.1.0, but new features only work with the updated version.

3. Build/Consumer Separation

With Maven 3, a library’s POM includes build metadata like plugin configurations. This bloats dependency resolution and exposes internal details.

Maven 4 separates the Build POM from the Consumer POM. We keep the Build POM as before, and Maven generates a Consumer POM for dependency users.

A Consumer POM excludes build-specific info, parent POM references, and unused dependencies. It only includes transitive dependencies and managed dependencies that the project uses. Properties are resolved in place.

We call the transformation “flattening”. Maven 3 required the Flatten Maven Plugin, but the new versions of the Maven Install and Deploy plugins handle it natively when we use this command-line option:

mvn \
  clean install \
  -Dmaven.consumer.pom.flatten=true

4. New Artifact Types

For dependencies, we could specify a <type> to reference artifacts with non-default packaging. Maven defines several types in the Default Artifact Handlers Reference.

For a normal JAR, Maven adds it to the classpath. If the JAR contains module-info.class, Maven adds it to the module path, assuming that we use Java Modules. Maven 4 adds <type>classpath-jar</type> and <type>module-jar</type> to control this explicitly.

We also get new types to simplify annotation processor registration: processor, classpath-processor, and modular-processor. We just add dependencies instead of configuring plugins such as the maven-compiler-plugin.

For example, with Lombok and Maven 4, we could write:

<project>
  <properties>
    <lombok.version>1.18.42</lombok.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
      <type>classpath-processor</type>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

We need both dependencies because Maven 4 separates API and processor classpaths.

In future releases, Maven might extend the list of types, e.g., for extending the taglet or doclet path.

5. Subprojects

Maven Modules got confusing when Java 9 introduced Java Modules. As a consequence, Maven 4 renames the term Modules to Subprojects. We now have a subprojects element in the POM, while the modules element is marked as deprecated:

<subprojects>
    <subproject>project-a</subproject>
    <subproject>project-b</subproject>
</subprojects>

And there are some other improvements:

  • Parent Inference: We can use an empty parent element with no coordinates. Maven infers it from the Aggregator POM.
  • Subprojects Discovery: We can omit the subprojects element, and Maven finds all subfolders with a pom.xml.
  • Consistent Timestamps in packaged archives for all subprojects
  • Safe Deployment: If one subproject fails, the others are not deployed to the repositories either.

6. Lifecycle Improvements

Maven 4 introduces a tree-based lifecycle. Each project moves through phases independently, and dependent projects start once dependencies reach their ready phase. This boosts performance for multi-project builds. We enable it with:

mvn -b concurrent verify

Each phase now has before: and after: hooks. These replace older pre- and post-phases, which are now aliases for backwards compatibility. For example, maven-gpg-plugin:sign can bind to before:install instead of verify, which would be semantically correct. after: hooks only run if the main phase succeeds.

Maven 4 also adds all and each phases with hooks. These help us run logic once per project tree or around each phase, making multi-project builds more predictable.

7. Further Changes

Some smaller changes affect upgrades:

  • Activating a non-existing profile with -PmyProfile fails. Use -P?myProfile to make the profile optional and avoid failure.
  • We can use –fail-on-severity or -fos to fail builds at a log level.

We now look at a few more changes that improve Maven 4’s flexibility.

7.1. Condition-Based Profile Activation

Maven 4 adds a condition element for profile activation. This allows us to declare complex expressions using functions:

<project>
  <!-- ... -->
  <profiles>
    <profile>
      <id>conditional-profile</id>
      <activation>
        <!-- use <condition><![CDATA[...]]></condition> to avoid encoding XML entities -->
        <condition>exists('${project.basedir}/src/** /*.xsd') &amp;&amp; length(${user.name}) > 5</condition>
      </activation>
      <!-- ... -->
    </profile>
  </profiles>
</project>

7.2. Source Directories

In Maven 3, we declare custom source roots with two dedicated elements. This works, but it is limited when we want multiple directories or fine-grained filtering:

<project>
  <!-- Maven 3 -->
  <build>
    <sourceDirectory>my-custom-dir/foo</sourceDirectory>
    <testSourceDirectory>my-custom-dir/bar</testSourceDirectory>
  </build>
</project>

Maven 4 introduces a unified sources section. We can list as many source roots as we need, assign a scope, and prepare more advanced setups without extra plugins:

<project>
  <!-- Maven 4 -->
  <build>
    <sources>
      <source>
        <scope>main</scope>
        <directory>my-custom-dir/foo</directory>
      </source>
      <source>
        <scope>test</scope>
        <directory>my-custom-dir/bar</directory>
      </source>
    </sources>
  </build>
</project>

This new model scales well for multi-release projects, module-based layouts, and cases where we want to apply include or exclude rules directly in the POM.

8. Maven 4 Upgrade Tool

Maven 4 adds an Upgrade Tool to migrate projects from Maven 3. It scans POMs, plugins, and structure, then recommends updates.

We can run it with:

mvnup apply

If we only want to get a report of what changes the tool suggests, without modifying pom.xml, we could do a dry run:

mvnup check

9. Conclusion

In this tutorial, we have learned that Maven 4 modernizes Java builds with a clearer POM model, separated build and consumer artifacts, and better support for modules and annotation processors. The updated lifecycle improves multi-project and concurrent builds. Hooks give us precise control, and smaller changes improve reproducibility.

The Upgrade Tool eases migration from Maven 3. Overall, Maven 4 boosts performance, clarity, and maintainability, laying a solid foundation for modern Java projects.

As always, the code presented in this article is available over on GitHub.

The post What’s New in Maven 4 first appeared on Baeldung.
       

 

Content mobilized by FeedBlitz RSS Services, the premium FeedBurner alternative.