Example example_automatic-module-logging
Part of the full Java 9 Jigsaw modules example suite.
|
Authors
Originally written by Martin Lehmann, Kristine Schaal and RĂ¼diger Grammes (cf. original repository). Migrated for Java Modules support documentation of Apache MavenTM in the course of the Maven Support & Care program by Gerd Aschemann (and other team members) as forked repository. Please add discussions, requirements, bugfixes, etc. to the fork instead of the original. |
What is this example about?
Modules in this example
-
modmain
-
slf4j*.jar as automatic modules
-
modmain has a Main class which is started in run.sh
Module Dependency Graph, created with DepVis
Example shows …
The example illustrates the usage of automatic modules with logging. We use three logging libs as automatic modules:
-
slf4j-api-1.7.12.jar contains the logging interfaces (see directory ifamlib).
-
slf4j-jdk14-1.7.12.jar and slf4j-simple-1.7.12.jar contain implementations for slf4j (see directory amlib).
The main class writes some logging output. The run script runs the main class twice, once with slf4j-jdk14 as implementation, once with slf4j-simple-1.7.12 as implementation.
The example also shows:
-
during compile time, only the interfaces are needed
-
the mapping of names in automatic modules: The part behind the last "-" is interpreted as version and cut off. Each remaining "-" is substituted by a ".".
Output
This example uses golden master testing to ensure output consistency.
The expected output is compared with actual output using verify.sh.
Expected Output
<TIMESTAMP> pkgmain.Main main
INFO: This is Main - logging.
[main] INFO pkgmain.Main - This is Main - logging.
Error occurred during initialization of boot layer
java.lang.module.ResolutionException: ...
Maven 4 Migration
This example required special handling for automatic module dependencies when migrating to Maven 4’s Module Source Hierarchy.
Maven 4 Compiler Changes
The Challenge
By default, Maven places all dependencies on the --class-path, but automatic modules must be on the --module-path to be recognized by the module system.
When slf4j-api-1.7.12.jar is on the classpath, the compiler cannot resolve:
requires slf4j.api; // Module not found!
The module name slf4j.api is derived from the JAR filename when it’s treated as an automatic module on the module-path.
The Solution
The solution involves two steps:
-
Copy dependencies to a local directory using
maven-dependency-plugin:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.8.1</version> <executions> <execution> <id>copy-dependencies</id> <phase>generate-sources</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.basedir}/amlib-api</outputDirectory> </configuration> </execution> </executions> </plugin> -
Add the directory to
--module-pathvia compiler configuration:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>4.0.0-beta-3</version> <configuration> <compilerArgs> <arg>--module-path</arg> <arg>${project.basedir}/amlib-api</arg> </compilerArgs> </configuration> </plugin>
This approach ensures that slf4j-api JAR is on the module-path during compilation.
It allows the JAR to be recognized as an automatic module with the derived name slf4j.api.
Key Takeaways
-
Automatic modules must be on
--module-path, not--class-path -
Maven dependency plugin can copy JARs to a local directory
-
The
--module-pathcompiler argument can be extended via<compilerArgs> -
Module names for automatic modules are derived from JAR filenames (version numbers stripped, hyphens converted to dots)