0% found this document useful (0 votes)
57 views37 pages

Migrating to Java 9 Modules Guide

1. Modules define explicit dependencies and encapsulate packages by default. 2. Packages can be "opened" to allow deep reflection at runtime via the "opens" directive. 3. By default, only reflection on public APIs is allowed; deep reflection is denied to prevent security issues.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views37 pages

Migrating to Java 9 Modules Guide

1. Modules define explicit dependencies and encapsulate packages by default. 2. Packages can be "opened" to allow deep reflection at runtime via the "opens" directive. 3. By default, only reflection on public APIs is allowed; deep reflection is denied to prevent security issues.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Migrating to Java 9

Modules

| Paul Bakker
Why care about modules?
lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/rest-api-client-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/gradle-extra-configurations-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/gradle-lint-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/gradle-resolution-rules-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/nebula-dependency-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/httpclient-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/commons-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/jackson-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/commons-
[Link]:lib/[Link]-jdk16-1.46_3.jar:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/metatron-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/multiverse-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
error_prone_annotations-[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/grpc-
[Link]:lib/[Link]:lib/[Link]:lib/xpp3_min-[Link]:lib/[Link]:lib/grpc-google-common-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/spring-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/commons-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]-trilead-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/antlr-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/bcprov-
[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/[Link]:lib/
[Link]:lib/[Link]
Module primer.
module [Link] {
module [Link] { exports [Link];
requires [Link]; opens impl;
} }

[Link] [Link]
[Link]
impl
reflection only!
other
Module primer.
module [Link] {
module [Link] { exports
Modules [Link];
dependencies
requires [Link]; opensexplicitly
impl;
} }

[Link] [Link]
[Link]
impl
reflection only!
other
Module primer.
module [Link] {
module [Link] { exports [Link];
requires [Link]; opens impl;
Packages are encapsulated by
} }
default

[Link] [Link]
[Link]
impl
reflection only!
other
Module primer.
module [Link] {
module [Link] { exports [Link];
requires Packages
[Link];
can be “opened” for opens impl;
} deep reflection at run-time }

[Link] [Link]
[Link]
impl
reflection only!
other
Migrating to Java 9.
Java 8

java -cp … -jar


[Link]
Java 9

java -cp … -jar


[Link]
Our journey to modules.
Running on Java 9
Using existing libraries
Allowing reflection
Spring / Hibernate case study
Refactoring to increase modularity
Migrating builds
!"" lib
!"" [Link]
#"" src
!"" books
$   !"" api
$   $   !"" entities
$   $   $   #"" [Link]
$   $   #"" service
$   $   #"" [Link]
$   #"" impl
$   !"" entities
$   $   #"" [Link]
$   #"" service
$   #"" [Link]
!"" bookstore
$   !"" api
$   $   #"" service
$   $   #"" [Link]
javac -cp [list of JARs in lib]
$   #"" impl -d out -sourcepath src $(find src -name '*.java')
$   #"" service
$   #"" [Link] cp $(find src -name '*.xml') out
!"" [Link]
!"" main java -cp [list of JARs in lib]:out [Link]
$   #"" [Link]
#"" [Link]
Missing platform libraries.
import [Link];

public class Main {

public static void main(String... args) {


DatatypeConverter.parseBase64Binary("SGVsbG8gd29ybGQh");
}
}

[Link]: [Link]
The platform module graph.
[Link] vs [Link]
Resolving JAXB.

java --add-modules [Link] …


Illegal deep reflection.

WARNING: An illegal reflective access operation has occurred


WARNING: Illegal reflective access by
[Link] …
WARNING: Please consider reporting this to the maintainers of
[Link]

WARNING: Use --illegal-access=warn to enable warnings of further


illegal reflective access operations

WARNING: All illegal access operations will be denied in a future


release
Type Compile time Reflection on public Deep reflection

Exports
✓ ✓ ✘
Open
✘ ✓ ✓
Exports + Open
✓ ✓ ✓
Fixing illegal deep reflection.

Use a library that doesn’t do this!


do you really need deep reflection on JDK types!?

Use command line flags to open packages

java --add-opens [Link]/[Link]=ALL-UNNAMED Main


Automatic
Modules
But we’re still on the classpath!
Let’s migrate our code to
modules

But how do we deal with


libraries?
package demo;

import [Link];

public class Main {

public static void main(String... args) throws Exception {


Book modularityBook =
new Book("Java 9 Modularity", "Modularize all the things!");

ObjectMapper mapper = new ObjectMapper();


String json = [Link](modularityBook);
[Link](json);

}
}

module books {

}
Automatic modules - A non-
modular JAR on the module
path
Exports all packages
Requires all resolved modules
Can read the class path (the unnamed module)
module books {
requires [Link];
}

CP=lib/[Link]:
CP+=lib/[Link]

javac -cp $CP --module-path mods -d out --module-source-path src -m books


Case study
Sample app after migration.
!"" lib
!""
!""
mods
[Link]
Step 1 - Project structure.
#"" src
#"" bookapp “mods” dir for automatic modules
!"" books
$   !"" api
Single module dir (for now)
$   $   !"" entities Add [Link]
$   $   $   #"" [Link]
$   $   #"" service
$   $   #"" [Link]
$   #"" impl
$   !"" entities
javac -cp $CLASSPATH \
$  
$  
$   #"" [Link]
#"" service
--module-path mods \
$   #"" [Link] -d out \
!"" bookstore
$   !"" api --module-source-path src \
$   $   #"" service
$   $   #"" [Link] -m bookapp
$   #"" impl
$   #"" service
$   #"" [Link]
!"" [Link]
!"" main
$   #"" [Link]
!"" [Link]
#"" [Link]
Step 2 - Add requires.

Compilation error
[Link]: error: package
[Link] is not visible
import [Link];

Our module needs explicit


dependencies!
Step 3 - Add missing compile time platform
modules.

Compilation error
[Link]: error: cannot access Referenceable
return [Link]().get([Link], id);
^
class file for [Link] not found

Hibernate should declare


requires transitive [Link]
Running.

java -cp $CLASSPATH


--module-path mods:out
-m bookapp/[Link]
Step 4 - Add missing platform modules.

[Link]: [Link]

java -cp $CLASSPATH


--add-modules [Link],[Link]
--module-path mods:out
-m bookapp/[Link]
Step 5 - Open packages for reflection.

[Link]: class
[Link] cannot access class
[Link] (in module bookapp)
because module bookapp does not export [Link] to
unnamed module @5c45d770

opens [Link];
opens [Link];
opens [Link];
Step 6 - Illegal deep reflection.
[Link]: Unable to make
protected final [Link]
[Link]([Link],byte[],int,int
,[Link]) throws
[Link] accessible: module [Link] does not
"opens [Link]" to module javassist

java -cp $CLASSPATH


--add-modules [Link],[Link]
--add-opens [Link]/[Link]=javassist
--module-path mods:out
-m bookapp/[Link]
Refactor to
multiple modules
Multi module structure
requires
[Link] [Link]

main requires

bookstore
requires Spring
requires
[Link] [Link]

main requires

[Link] [Link]
requires
provides

uses provides
Module System
Build tools. <artifactId>bookstore</artifactId>
<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
module bookstore {
<artifactId>maven-compiler-plugin</artifactId>
requires books;
<configuration>
<source>9</source>
exports [Link];
<target>9</target>
</configuration>
uses [Link];
</plugin>
</plugins>
provides [Link] with
</build>
[Link];
<dependencies>
}
<dependency>
<groupId>javamodularity</groupId>
<artifactId>books</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
Thank you.
Paul Bakker
@pbakker

You might also like