#DevoxxFR
Apache Maven and Java 9 ( & 10 & ..)
Robert Scholte @rfscholte
Hervé Boutemy @hboutemy
#DevoxxFR
The good news
Apache Maven runs fine on Java 9 (and 10 and … )
Possible issues are often plugin related
Upgrading to the latest version should solve the problem
#DevoxxFR
Applying a module descriptor
1. Just add your module-info.java to src/main/java
2. Upgrade maven-compiler-plugin to at least 3.7.0
3. There’s no step three
Maven will calculate which dependencies belong to the
classpath and which to the module path.
No new dependency-element/scope
#DevoxxFR
When two worlds
collide…
#DevoxxFR
Maven
Java
< 8
#DevoxxFR
Maven
Java
< 8Java 9
#DevoxxFR
Library builders should be aware of the
impact of their module descriptors
Application builders should recognize these
issues
If you’re not careful with your modularization
you can corrupt the whole Maven Ecosystem
#DevoxxFR
Module names
#DevoxxFR
Déjà Vu
What is the proper module name?
What is the proper groupId and artifactId?
#DevoxxFR
• Modulenames with numbers
• Automatic module names
Module names must be
as unique as the coordinates of
dependencies
#DevoxxFR
Modulenames with numbers
Project/product names
• AWS-EC2
• AWS-Route53
• AWS-S3
• C3P0
• DB2
• Fabric8
• H2
• JSRnnn
• OAuth2
Versioned libraries
(includes versioned
packages)
• Commons-lang2
• Commons-lang3
Bridge libraries to
different versions
• Jspc-compiler-
tomcatN
• Mockwire-springN
• Surefire-junitN
Close to 30.000 groupId/artifactId end with a number (Central, March 2017)
#DevoxxFR
#VersionsInModuleName
s
Some have argued that library
maintainers will be tempted to
encode major version numbers, or
even full version numbers, in
module names. Is there some way
we can guide people away from
doing that?
Resolution Abandon the previous
proposal to mandate that module
names appearing in source-form
module declarations must both start
and end with “Java letters”. Revise
the automatic-module naming
algorithm to allow digits at the end
of module names.
#DevoxxFR
Automatic module names
“… . The module name is otherwise derived from the name of
the JAR file.”
#DevoxxFR
NPM Javascript package
registry
Over 13500 ‘rows’
Evidence (OCT
2016)
#DevoxxFR
Jigsaw
Automatic modules are required for
top-down adoption
Maven
References to automatic module
names will cause collisions sooner
or later
Library builders should never refer to automatic modules* and deploy to a public repository.
Application builders can choose to refer to automatic modules.
#DevoxxFR
Application
Module descriptor without exports
maven-compiler-plugin logs info
message in case of automatic
module usage
Library
Module descriptor with exports
Tip: Use Maven 3.5.0+ for colour support
maven-compiler-plugin logs
WARNING message in case of
automatic module usage
#DevoxxFR
Automatic modules
Ease of top-down migration for application builders
But what about “in the middle” library builders?
#DevoxxFR
JSR 376: JavaTM Platform Module System
Original Java Specification Request (JSR)
Section 2.1
Java Platform. It will be approachable, i.e., easy to
learn and easy to use, so that developers can use it
to construct and maintain libraries and large
applications for both the Java SE and Java EE
Platforms.
#DevoxxFR
Conference example
Application my-app
Libraries jackson-core jackson-databind jackson-annotations my-lib
java.base
#DevoxxFR
More realworld example
Application my-app
Libraries (direct deps) … … … my-lib
Libraries (transitive deps)
…
… … …
Libraries (independent deps) jackson-core jackson-databind jackson-annotations
java.base
#DevoxxFR
1library-a-1.0.jar
#DevoxxFR
2library-b-1.0.jar
module org.lib.b
{
requires library.a; // from filename
}
#DevoxxFR
3library-a-2.0.jar
module com.lib.a
{
}
#DevoxxFR
4library-c-1.0.jar
module org.lib.c
{
requires com.lib.a; // from descr.
}
#DevoxxFR
5app-d-1.0.jar
module org.app.d
{
requires com.lib.b;
requires com.lib.c;
}
#DevoxxFR
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.d</groupId>
<artifactId>app-d</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<!-- the dependencies -->
</dependencies>
</project>
#DevoxxFR
<dependency>
<groupId>org.organization.b</groupId>
<artifactId>lib-b</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.foundation.c</groupId>
<artifactId>lib-c</artifactId>
<version>1.0</version>
</dependency>
#DevoxxFR
app-d.jar (org.app.d)
requires com.lib.b;
requires com.lib.c;
library-b-1.0.jar (org.lib.b)
requires library.a;
library-c-1.0.jar (org.lib.c)
requires com.lib.a;
#DevoxxFR
app-d.jar (org.app.d)
requires com.lib.b;
requires com.lib.c;
library-b-1.0.jar (org.lib.b)
requires library.a;
library-a-1.0.jar
(library.a)
library-c-1.0.jar (org.lib.c)
requires com.lib.a;
library-a-2.0.jar
(com.lib.a)
#DevoxxFR
app-d.jar (org.app.d)
requires com.lib.b;
requires com.lib.c;
library-b-1.0.jar (org.lib.b)
requires library.a;
library-a-1.0.jar
(library.a)
library-c-1.0.jar (org.lib.c)
requires com.lib.a;
library-a-2.0.jar
(com.lib.a)
#DevoxxFR
<dependency>
<groupId>org.organization.b</groupId>
<artifactId>lib-b</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.foundation.c</groupId>
<artifactId>lib-c</artifactId>
<version>1.0</version>
</dependency>
#DevoxxFR
app-d.jar (org.app.d)
requires com.lib.b;
requires com.lib.c;
library-c-1.0.jar (org.lib.c)
requires com.lib.a;
library-a-2.0.jar
(com.lib.a)
library-b-1.0.jar (org.lib.b)
requires library.a;
library-a-1.0.jar
(library.a)
#DevoxxFR
app-d.jar (org.app.d)
requires com.lib.b;
requires com.lib.c;
library-c-1.0.jar (org.lib.c)
requires com.lib.a;
library-a-2.0.jar
(com.lib.a)
library-b-1.0.jar (org.lib.b)
requires library.a;
library-a-1.0.jar
(library.a)
#DevoxxFR
Migrate
META-
INF/MANIFEST.MF
• Automatic-Module-Name
#DevoxxFR
2library-b-1.0.jar
META-INF/MANIFEST.MF
Automatic-Module-Name: org.lib.b
#DevoxxFR
Point of
no return
“If you refer to
dependency X:N as a
module and
dependency X:N-1
has no module name,
then you cannot
downgrade
dependency X
anymore”
#DevoxxFR
library-a-1.0.jar
(library.a)
library-c-1.0.jar
(org.lib.c)
requires com.lib.a;
library-a-2.0.jar
(com.lib.a)
#DevoxxFR
Strong advices
-Project must be Java 9 ready!!
o No split packages
o No root classes
-For libraries that depends on at least one filename based
automodule:
o Help depending projects by providing intended module name via
MANIFEST
-Pick your modulename with care, e.g. the shared package
#DevoxxFR
Mistakes will happen
In fact, first invalid modules are already available at Maven Central
asm-6.0_BETA ( org.ow2.asm)
asm-all-6.0_BETA (org.ow2.asm.all) 1
asm-debug-all-6.0_BETA (org.ow2.asm.debug.all) 1
Application developer cannot fix these mistakes (dependency-exclude
doesn’t work)
1 Fixed with asm-6.0 by dropping *-all artifacts (asm includes debug
information by default)
Same packages
must have the
same modulename
(otherwise potential
split package issue)
#DevoxxFR
Tips for using JAVA 9 with MAVEN
DON’T change your folder structure (no need for extra folder
with module name)
Modulepath or classpath? No change to dependencies, just
add module-info.java ( Plexus-java can help plugins to build up
the path )
#DevoxxFR
Issues?
1) Stackoverflow
2) Apache Maven mailinglists
3) Apache Maven Jira in case of bugs / improvements
#DevoxxFR
Source / target 1.9
<release>9<release>
source/target <= 1.8 : animal-sniffer
#DevoxxFR
Questions?
#DevoxxFR
Can every project become modular?
NO
-Java 9 is a gamechanger, it introduces new rules
-The older the project, the more likely it cannot follow these
rules
-No worries, the classpath is still there and will stay!
#DevoxxFR
The boomerang question
Or “the ever returning Maven/Java9/Conference question”
Will Maven generate the module
descriptor?
#DevoxxFR
No
Different purpose
Pom is used to download jars and
make them available
Module descriptor is used to specify
required modules
Not all modules are dependencies ( e.g.
java.logging, jdk.compiler )
#DevoxxFR
No
Module descriptor elements not covered:
Module name
Open module
Exported packages
Uses / provides services
Pom 4.0.0 has no space for new elements
#DevoxxFR
Pom hygiene
dependency:analyse
Analyzes the dependencies of this project and determines which are:
used and declared (good)
used and undeclared (via transitive dependency)
unused and declared (ballast!)
Dependencies can be excluded, required modules cannot
#DevoxxFR
…BUT JDEPS can do it, right?
Can create a rough module descriptor
Intended to help with an initial descriptor
Uses binary classes, i.e. AFTER compile-phase
#DevoxxFR
Some open source project will…
https://github.com/moditect/moditect
#DevoxxFR
Other Questions?
#DevoxxFR
THANK YOU
@ASFMAVENPROJECT

Apache Maven and Java 9 and 10 (Devoxx France 2018)

Editor's Notes

  • #34 Modules don’t have aliases. Always exactly one name (or none)
  • #35 Modules don’t have aliases. Always exactly one name (or none)