-
Notifications
You must be signed in to change notification settings - Fork 0
Migration
This page lists some usage patterns of Maven 3 which have changed in Maven 4.
The Maven 3 elements are deprecated and should be replaced by the new <sources> element introduced in Maven 4.
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
</build><build>
<sources>
<source>
<directory>src/main/java</directory>
</source>
<source>
<scope>test</scope>
<directory>src/test/java</directory>
</source>
</sources>
<build>Note that the declaration of a <sources> element replaces the default values,
hence the need to declare the source and test directories together.
The new <source> element allows more flexibility such as specifying many directories,
the include/exclude filters, the targeted Java release and more.
The external plugin used in Maven 3 is no longer needed
and should be replaced by the build-in <sources> elements.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-directory</id>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/extension/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build><build>
<sources>
<source>
<directory>src/main/java</directory>
</source>
<source>
<directory>src/extension/java</directory>
</source>
<source>
<scope>test</scope>
<directory>src/test/java</directory>
</source>
</sources>
<build>Reminder: because <sources> replaces the default values, these defaults need to be explicitly specified.
The new compiler plugin handles automatically multiple executions of javac with different --release option values,
and with automatic adjustments of class-path and output directories for producing a multi-releases project.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile-java-17</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>17</release>
</configuration>
</execution>
<execution>
<id>compile-java-21</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>21</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java_21</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build><build>
<sources>
<source>
<directory>src/main/java</directory>
<targetVersion>17</targetVersion>
</source>
<source>
<directory>src/main/java_21</directory>
<targetVersion>21</targetVersion>
</source>
<source>
<scope>test</scope>
<directory>src/test/java</directory>
</source>
</sources>
</build>The Maven 3 way to declare include/exclude filters is still supported,
but should be replaced by the <sources> element when applicable.
Those two ways are not strictly equivalent:
- The Maven 4 way specifies filters independently for each source directory. These filters will be applied by all plugins that migrated to the Maven 4 API, not only the compiler plugin.
- Conversely, the Maven 3 way specifies filters which will be applied only by the compiler plugin. However, these filters apply to all source directories.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/Foo*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build><build>
<sources>
<source>
<directory>src/main/java</directory>
<excludes>
<exclude>**/Foo*.java</exclude>
</excludes>
</source>
<source>
<scope>test</scope>
<directory>src/test/java</directory>
</source>
</sources>
</build>The Maven 3 way to make a modular project is to put a module-info.java file in the root directory of Java source files.
Because the compilation and execution of tests usually require an amended version of module information,
Maven 3 allows to overwrite that file with another module-info.java file placed in the test source directory.
While this approach is still supported in Maven 4 for compatibility reasons,
it is deprecated and may no longer be supported in a future version.
Developers are strongly encouraged to migrate to the approach described in this section.
The directory layout was as below:
src
├─ main
│ └─ java
│ ├─ module-info.java
│ └─ my/product/*.java
├─ test
│ └─ java
│ ├─ module-info.java
│ └─ my/product/*.java
└─ target
└─ classes
An alternative to test/java/module-info.java was to declare compiler arguments
such as --add-reads in the <testCompilerArgs> element of the plugin configuration.
Same directory layout as Maven 3 with only test/java/module-info.java removed.
This approach can be used when compatibility with Maven 3 is required.
src
├─ main
│ └─ java
│ ├─ module-info.java
│ └─ my/product/*.java
├─ test
│ └─ java
│ └─ my/product/*.java
└─ target
└─ classes
The Maven compiler automatically adds --patch-module and --add-reads arguments for compiling the tests.
In many cases (but not always), a <testCompilerArgs> plugin configuration is unnecessary.
See the user guide for more information. This approach is recommended for new projects, (TODO: pending upgrade of other Maven plugins) as it makes the best use of compiler options dedicated to modular projects.
src
├─ java
│ └─ my.product.foo
│ ├─ main
│ │ ├─ module-info.java
│ │ └─ my/product/*.java
│ └─ test
│ └─ my/product/*.java
└─ target
└─ classes
└─ my.product.foo
Above layout needs to be declared with the following section in the pom.xml file:
<build>
<sources>
<source>
<module>my.product.foo</module>
<directory>src/java/my.product.foo/main</directory>
</source>
<source>
<module>my.product.foo</module>
<directory>src/java/my.product.foo/test</directory>
<scope>test</scope>
</source>
</sources>
</build>The Maven compiler automatically adds --patch-module and --add-reads arguments for compiling the tests.
In many cases (but not always), a <testCompilerArgs> plugin configuration is unnecessary.