Meet Java Modules

List module files

ls -al  /usr/lib/jvm/jdk-9/jmods/
total 134544
drwxr-xr-x 2 root root     4096 wrz  2 15:17 .
drwxr-xr-x 8 root root     4096 wrz 24 16:35 ..
-rw-r--r-- 1 uucp  143    60992 sie  3 06:24 java.activation.jmod
-rw-r--r-- 1 uucp  143 19179351 sie  3 06:24 java.base.jmod
-rw-r--r-- 1 uucp  143   111302 sie  3 06:24 java.compiler.jmod
-rw-r--r-- 1 uucp  143  2680154 sie  3 06:24 java.corba.jmod
-rw-r--r-- 1 uucp  143    51795 sie  3 06:24 java.datatransfer.jmod
-rw-r--r-- 1 uucp  143 15766124 sie  3 06:24 java.desktop.jmod
-rw-r--r-- 1 uucp  143   765862 sie  3 06:24 javafx.base.jmod
-rw-r--r-- 1 uucp  143  2511426 sie  3 06:24 javafx.controls.jmod
-rw-r--r-- 1 uucp  143   238532 sie  3 06:24 javafx.deploy.jmod
(...)
-rw-r--r-- 1 uucp  143   119985 sie  3 06:24 java.logging.jmod
-rw-r--r-- 1 uucp  143   880650 sie  3 06:24 java.management.jmod
-rw-r--r-- 1 uucp  143    90550 sie  3 06:24 java.management.rmi.jmod
-rw-r--r-- 1 uucp  143   443764 sie  3 06:24 java.naming.jmod
-rw-r--r-- 1 uucp  143    62499 sie  3 06:24 java.prefs.jmod

jmod

jmod describe  /usr/lib/jvm/jdk-9/jmods/java.base.jmod 
java.base@9
exports java.io
exports java.lang
exports java.lang.annotation
exports java.lang.invoke
exports java.lang.module
exports java.lang.ref
exports java.lang.reflect
exports java.math
...

list modules

java --list-modules | column

java -d java.sql
java.sql@9
exports java.sql
exports javax.sql
exports javax.transaction.xa
requires java.base mandated
requires java.logging transitive
requires java.xml transitive
uses java.sql.Driver

module system

Intro

We are going to use Intellij 2017.3 or newer. In this workshop perform actions step by step.

Create New Project

File -> New -> Project -> Empty Project

Name : modulesjug

Create New Java Module

  • Name : com.jug.modules.intro.math

  • Press F4 and in project settings choose language level Java 9

  • Alt + Insert on src -> new module.info.java

Create New Package

  • Name : com.jug.modules.intro.math

  • Create New Class MathLib.java

package com.jug.modules.intro.math;

import java.util.Optional;

public class MathLib {

    public static Optional<Integer> add(Integer i1, Integer i2){
        return Optional.of(i1+i2);
    }

}
  • Create Main class _math _package
package com.jug.modules.intro.math;

public class MathMain {
    public static void main(String[] args) {
        System.out.println("adding in math lib : "+MathLib.add(1,2));
    }
}
  • create empty folder mods

    mkdir mods
    
    >ls
    com.jug.modules.intro.math  mods
    
  • compile module

javac -d mods/mods/com.jug.modules.intro.math  com.jug.modules.intro.math/src/module-info.java /
com.jug.modules.intro.math/src/com/jug/modules/intro/math/MathLib.java /
com.jug.modules.intro.math/src/com/jug/modules/intro/math/MathMain.java
tree mods
mods
└── com.jug.modules.intro.math
    ├── com
    │   └── jug
    │       └── modules
    │           └── intro
    │               └── math
    │                   ├── MathLib.class
    │                   └── MathMain.class
    └── module-info.class
  • Run Module
java --module-path mods -m com.jug.modules.intro.math/com.jug.modules.intro.math.MathMain
adding in math lib : Optional[3]

Module Encapsulation

  • add internal package
package com.jug.modules.intro.math.internal
  • Put there utility class OverflowDetector
public class OverflowDetector {
    public static Optional<Integer> add(int a, int b){
        try{
            return Optional.of(java.lang.Math.addExact(a,b));
        }catch(Exception e){
            return Optional.empty();
        }
    }
}
  • export main package
module com.jug.modules.intro.math {
    exports com.jug.modules.intro.math;
}
  • compile full module
javac -d mods/com.jug.modules.intro.math $(find com.jug.modules.intro.math/src/ -name *.java)
  • show modules description
java --module-path mods  --describe-module com.jug.modules.intro.mathcom.jug.modules.intro.math 
file:///home/pawel/projects/workshops/modulesjug/mods/com.jug.modules.intro.math/
exports com.jug.modules.intro.math
requires java.base mandated

Second Module - Displayer

  • create new module com.jug.modules.intro.displayer in the same parent folder as math module.

  • add Displayer class

package com.jug.modules.intro.displayer;

import com.jug.modules.intro.math.MathLib;

import java.util.Optional;
import java.util.Scanner;
import java.util.function.Consumer;

public class Displayer {

    private static Consumer<Integer> printResult=(i) -> System.out.println("result is : "+i);
    private static Runnable errorProcedure = () -> System.out.println("unable to add integeres, overflow");

    public static void displayMath(){
        Scanner scanner = new Scanner(System.in);
        System.out.print("i1 : ");
        Integer i1=scanner.nextInt();
        System.out.print("i2 : ");
        Integer i2=scanner.nextInt();


        Optional<Integer> result = MathLib.add(i1, i2);

        result.ifPresentOrElse(printResult,errorProcedure);
    }

    public static void main(String[] args) {
        displayMath();
    }
}
  • try to compile
javac -d mods/com.jug.modules.intro.displayer $(find com.jug.modules.intro.displayer/src/ -name *.java)

com.jug.modules.intro.displayer/src/module-info.java:2: error: module not found: com.jug.modules.intro.math
    requires com.jug.modules.intro.math;
  • add module path
javac -d mods/com.jug.modules.intro.displayer --module-path mods  $(find com.jug.modules.intro.displayer/src/ -name *.java)
  • test displayer with input : MAX_INT = 2147483647
java --module-path mods -m com.jug.modules.intro.displayer/com.jug.modules.intro.displayer.Displayer

i1 : 2147483647
i2 : 2147483647
unable to add integeres, overflow
  • try to access internal math package
import com.jug.modules.intro.math.MathLib.internal;

com.jug.modules.intro.displayer/src/com/jug/modules/intro/displayer/Displayer.java:4: error: cannot find symbol
import com.jug.modules.intro.math.MathLib.internal;
  • remove math module and try to compile displayer
java --module-path mods -m com.jug.modules.intro.displayer/com.jug.modules.intro.displayer.Displayer
Error occurred during initialization of boot layer
java.lang.module.FindException: Module com.jug.modules.intro.math not found, required by com.jug.modules.intro.displayer
  • compile math once again
javac -d mods/com.jug.modules.intro.math  $(find com.jug.modules.intro.math/src/ -name *.java)
  • java --show-module-resolution
java --show-module-resolution --limit-modules com.jug.modules.intro.math  --module-path mods -m com.jug.modules.intro.displayer
root com.jug.modules.intro.displayer file:///home/pawel/projects/workshops/modulesjug/mods/com.jug.modules.intro.displayer/
com.jug.modules.intro.displayer requires com.jug.modules.intro.math file:///home/pawel/projects/workshops/modulesjug/mods/com.jug.modules.intro.math/
module com.jug.modules.intro.displayer does not have a MainClass attribute, use -m <module>/<main-class>
  • decompile
Compiled from "module-info.java"
module com.jug.modules.intro.displayer {
  requires com.jug.modules.intro.math;
  requires java.base;
}

Packaging to jars

jar --create --file modsjars/modules.math.jar -C mods/com.jug.modules.intro.math/ .
  • try to recompile displayer. Because we have math packed in jar so technically we have two modules with the same name
javac -d mods/com.jug.modules.intro.displayer --module-path mods  $(find com.jug.modules.intro.displayer/src/ -name *.java)
error: duplicate module on application module path
  module in com.jug.modules.intro.math
1 error
  • move Jar to different folder
javac -d mods/com.jug.modules.intro.displayer --module-path modsjars  $(find com.jug.modules.intro.displayer/src/ -name *.java)
jar --create --file modsjars/modules.displayer.jar --main-class com.jug.modules.intro.displayer.Displayer -C mods/com.jug.modules.intro.displayer/ .

java --module-path modsjars --module com.jug.modules.intro.displayer
i1 : 4
i2 : 7
result is : 11

//  --show-module-resultion
//  jar --list --file mods/modules.displayer.jar
//  jar --describe-module --file mods/monitor.observer.jar
// -Xlog:module*=debug:stdout:tid

Maven

parent pom

  • configure Java9
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>1.9</maven.compiler.target>
        <maven.compiler.source>1.9</maven.compiler.source>
</properties>
  • configure modules
<modules>
        <module>math</module>
        <module>calculator</module>
        <module>gui</module>
    </modules>
  • configure build plugin
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.7.0</version>
    <configuration>
        <source>9</source>
        <target>9</target>
        <showWarnings>true</showWarnings>
        <showDeprecation>true</showDeprecation>
    </configuration>
</plugin>

module pom

  • dependency on other module
  <dependencies>
        <dependency>
            <groupId>lodz.jug</groupId>
            <artifactId>calculator</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
   </dependencies>
  • module-info.java in src/main/java
module com.jug.modules.intro.gui {
    requires com.jug.modules.intro.calculator;
}

Compile Modules

mvn clean install

all jars will be saved in mods folder. Now try to run gui.

java --module-path mods --module com.jug.modules.intro.gui/com.jug.modules.intro.gui.Displayer

requires transitive

automatic naming

unnamed module

Persistence Framework

3) qualified exports

exports javamodularity.easytext.gui to javafx.graphics;

jdeps

deps math-1.0-SNAPSHOT.jar 
com.jug.modules.intro.math
 [file:///home/pawel/projects/workshops/mvnmodules/mods/math-1.0-SNAPSHOT.jar]
   requires mandated java.base (@9)
com.jug.modules.intro.math -> java.base
   com.jug.modules.intro.math                         -> com.jug.modules.intro.math.internal                com.jug.modules.intro.math
   com.jug.modules.intro.math                         -> java.io                                            java.base
   com.jug.modules.intro.math                         -> java.lang                                          java.base
   com.jug.modules.intro.math                         -> java.lang.invoke                                   java.base
   com.jug.modules.intro.math                         -> java.util                                          java.base
   com.jug.modules.intro.math.internal                -> java.lang                                          java.base
   com.jug.modules.intro.math.internal                -> java.util                                          java.base
  • with modules dependencies
jdeps --module-path mods mods/gui-1.0-SNAPSHOT.jar 

com.jug.modules.intro.gui
 [file:///home/pawel/projects/workshops/mvnmodules/mods/gui-1.0-SNAPSHOT.jar]
   requires com.jug.modules.intro.calculator
   requires mandated java.base (@9)
com.jug.modules.intro.gui -> com.jug.modules.intro.calculator
com.jug.modules.intro.gui -> java.base
   com.jug.modules.intro.gui                          -> com.jug.modules.intro.calculator                   com.jug.modules.intro.calculator

list modules + custom modules

java --module-path out --list-modules

Qualified exports

exports    moduleb.privateA    to    A;    //    Exported    only    to    module    A    
exports    moduleb.privateC    to    C;    //    Exported    only    to    module    C

java    -d    java.base    
        module    java.base@9
        ...    
        exports    jdk.internal.ref    to    java.desktop,    javafx.media    
        exports    jdk.internal.math    to    java.desktop    
        exports    sun.net.ext    to    jdk.net    
        exports    jdk.internal.loader    to    java.desktop,    java.logging

Optionality

require static

Reflection

  • show exception on setAccessible
xception in thread "main" java.lang.reflect.InaccessibleObjectException:
>Unable to make monitor.observer.DisconnectedServiceObserver()
>accessible: module monitor.observer does not "opens monitor.observer"
>to module monitor
provides javamodularity.easytext.analysis.api.Analyzer
with javamodularity.easytext.analysis.coleman.ColemanAnalyzer;
java.lang.module.FindException:
>Two versions of module org.slf4j.api found in mods
>(org.slf4j.api-1.5.3.jar and org.slf4j.api-1.7.7.jar)

JLink

jlink    --module-path
mods/:$JAVA_HOME/jmods    --add-modules    easytext.cli    \    --output    image

results matching ""

    No results matching ""