Migrating to Java 9 Modules

60
By Sander Mak Migrating to Java 9 Modules @Sander_Mak

Transcript of Migrating to Java 9 Modules

By Sander Mak

Migrating to Java 9 Modules

@Sander_Mak

Migrating to Java 9

java -cp .. -jar myapp.jarJava 8

Migrating to Java 9

java -cp .. -jar myapp.jar

java -cp .. -jar myapp.jar

Java 8

Java 9

Today's journey

Running on Java 9

Java 9 modules

Migrating to modules

Modularising code

Migrating to Java 9

Let's try it!

java -cp .. -jar myapp.jar

java -cp .. -jar myapp.jar

Java 8

Java 9

Classpath migration problems

‣ Unresolved platform modules ‣ (Ab)use of platform internals

Missing platform modules

error: package javax.xml.bind does not exist

import javax.xml.bind.DatatypeConverter;

public class Main {

public static void main(String... args) { DatatypeConverter.parseBase64Binary("SGVsbG8gd29ybGQh"); } }

Modular JDK

Modular JDK

Modular JDK

Modular JDK

Modular JDK

‣ Classpath compile-time “java.se” module is used

‣ This does not resolve: java.activationjava.corbajava.transactionjava.xml.bindjava.xml.wsjava.xml.ws.annotation

Missing platform modules

Add unresolved platform modulesjdeps demo/Main.class

Main.class -> java.base Main.class -> not found <unnamed> -> java.lang java.base <unnamed> -> javax.xml.bind not found

Find

javac --add-modules java.xml.bind demo/Main.java

Add unresolved platform modulesjdeps demo/Main.class

Main.class -> java.base Main.class -> not found <unnamed> -> java.lang java.base <unnamed> -> javax.xml.bind not found

Find

Fix

javac --add-modules java.xml.bind demo/Main.java

Add unresolved platform modules

java --add-modules java.xml.bind demo/Main.java

jdeps demo/Main.class

Main.class -> java.base Main.class -> not found <unnamed> -> java.lang java.base <unnamed> -> javax.xml.bind not found

Find

Fix

javac --add-modules java.xml.bind demo/Main.java

Add unresolved platform modules

java --add-modules java.xml.bind demo/Main.java

Let's try it!

public class Main {

public static void main(String... args) throws Exception { sun.security.x509.X500Name name = new sun.security.x509.X500Name("CN=user"); } }

Using encapsulated APIs

public class Main {

public static void main(String... args) throws Exception { sun.security.x509.X500Name name = new sun.security.x509.X500Name("CN=user"); } }

Using encapsulated APIs

Main.java:4: error: package sun.security.x509 does not exist

sun.security.x509.X500Name name = ^

jdeps -jdkinternals Main.class Main.class -> java.base Main -> sun.security.x509.X500Name JDK internal API (java.base)

JDK Internal API Suggested Replacement ---------------- --------------------- sun.security.x509.X500Name Use javax.security.auth.x500.X500Principal @since 1.4

Use jdeps to find problems

Using encapsulated APIsCompile with 1.8, run with 9:

Using encapsulated APIs

Exception in thread "main" java.lang.IllegalAccessError: class Main (in unnamed module @0x4cdbe50f) cannot access class sun.security.x509.X500Name (in module java.base) because module java.base does not export sun.security.x509 to unnamed module @0x4cdbe50f at Main.main(Main.java:4)

Compile with 1.8, run with 9:

Using encapsulated APIs

java --add-exports java.base/sun.security.x509=ALL-UNNAMED Main

Exception in thread "main" java.lang.IllegalAccessError: class Main (in unnamed module @0x4cdbe50f) cannot access class sun.security.x509.X500Name (in module java.base) because module java.base does not export sun.security.x509 to unnamed module @0x4cdbe50f at Main.main(Main.java:4)

Compile with 1.8, run with 9:

Using encapsulated APIs

Exception in thread "main" java.lang.IllegalAccessError: class Main (in unnamed module @0x4cdbe50f) cannot access class sun.security.x509.X500Name (in module java.base) because module java.base does not export sun.security.x509 to unnamed module @0x4cdbe50f at Main.main(Main.java:4)

Compile with 1.8, run with 9:

java --permit-illegal-access Main

New 'kill-switch':

Back to Modules...

main

books.api

books.impl

bookstore

Mental picture of your app

Actual view of your app

main

books.api

books.impl

bookstore

Java 9 modules make this possible!

Migrating to modules

Top down migrationcommons.lang3.3.4.jar demonstrator.jar

classpath

java.base module path

package com.javamodularity.demonstrator;

import org.apache.commons.lang3.StringUtils;

public class Demo {

public static void main(String args[]) { String output = StringUtils.leftPad("Leftpad FTW!", 20); System.out.println(output); } }

Classic classpath

package com.javamodularity.demonstrator;

import org.apache.commons.lang3.StringUtils;

public class Demo {

public static void main(String args[]) { String output = StringUtils.leftPad("Leftpad FTW!", 20); System.out.println(output); } }

Classic classpath

javac -cp lib/commons-lang3-3.4.jar -d out $(find src -name '*.java')

java -cp out:lib/commons-lang3-3.4.jar com.javamodularity.demonstrator.Demo

Compile

Run

Top down migrationcommons.lang3.3.4.jar demonstrator.jar

classpath

java.base module path

Top down migrationcommons.lang3.3.4.jar

demonstrator.jar

classpath

java.base module path

Can’t reference the classpath from named modules!

Top down migration

demonstrator.jar

classpath

java.base module path

commons.lang

But this isn’t our code!

Automatic Modules‣ A plain JAR on the module path becomes an

Automatic Module

‣ Module name derived from JAR name ‣ Exports everything ‣ Reads all other modules

module demonstrator { requires commons.lang; }

Using Automatic Modules

module demonstrator { requires commons.lang; }

Using Automatic Modules

javac --module-path lib --module-source-path src -d mods $(find src -name '*.java')

java --module-path mods:lib -m demonstrator/com.javamodularity.demonstrator.Demo

Compile

Run

Migrating the books app

1. Create a “monolith module” 2. Declare exports 3. Figure out “requires” 4. Move some libs to Automatic Modules

Step 2

commons.pool

spring.context

classpath

Application code

module path

spring.tx

hibernate.core hibernate.jpa

javax.inject

Automatic modules Named modules

commons.logging

spring.beans spring.aop

spring.core

hsqldb

spring.orm

commons.pool

spring.context

classpath

Application code

module path

spring.tx

hibernate.core

hibernate.jpa

javax.inject

Automatic modules Named modules

commons.logging

spring.beans spring.aop

spring.core

hsqldb

spring.orm

DEMO

Open Modules‣ Reliable configuration like normal modules ‣ Requires for every dependency ‣ Opens all packages for deep reflection

‣ Easy compatibility with existing code and frameworks ‣ Allows reflection

Type Compile time Reflection on public Deep reflection

Exports ✓ ✓ ✘

Open ✘ ✓ ✓Exports + Open ✓ ✓ ✓

Open Packages

Opens the package for deep reflection, but not compile time access

A package can be both open and exported

Tip 1

Move libraries to module path one by one

Start with direct dependencies

Tip 2

open when no compile time dependency should exist (possibly qualified)

Tip 3

requires only for direct dependencies

--add-modules for run-time dependencies

Tip 4

Use open modules for framework compatibility

Fine tune open later

Migrating the books app

1. Split monolith module 2. Move requires/exports 3. (optional) Move config files

Step 3

commons.pool

spring.context

classpath

Application code

module path

spring.tx

hibernate.core

hibernate.jpa

javax.inject

Automatic modules Named modules

commons.logging

spring.beans spring.aop

spring.core

hsqldb

spring.orm

commons.pool

spring.context

classpath

module path

spring.tx

hibernate.core

hibernate.jpa

javax.inject

Automatic modules Named modules

commons.logging

spring.beans spring.aop

spring.core

hsqldb

spring.orm

main books.api

books.impl

bookstore

Migration steps - recap

Migration steps - recap

‣ Migrate to Java 9 using classpath only

Migration steps - recap

‣ Migrate to Java 9 using classpath only‣ Create a module around your whole app

Migration steps - recap

‣ Migrate to Java 9 using classpath only‣ Create a module around your whole app‣ Modularize your application!

Thank you.

bit.ly/java9book @javamodularity

code @ bit.ly/java9mig

Thank you.

bit.ly/java9book @javamodularity

http://bit.ly/java9course

Java 9 Modularity: First Look

code @ bit.ly/java9mig