@aalmiray | andresalmiray.com
Building modular
applications with JPMS
and Layrry
Andres
Almiray
Seasoned Sourceror

@ Oracle

Apache Groovy PMC

Java Champion

Hackergarten

github.com/aalmiray
@aalmiray | andresalmiray.com
JPMS
• Java Platform Module System (also known as Jigsaw)

• Introduced in Java 9

• Designed to break down the JVM monolith

• Applicable to user space as well

• The promise is to give developers better code
encapsulation and design foundations
@aalmiray | andresalmiray.com
However …
@aalmiray | andresalmiray.com
Some user statements
• JPMS only allows for one version of a module

• JPMS doesn’t allow adding modules at runtime

• I have to modularize ALL dependencies to reap the
benefits of JPMS

• It’s so hard to map dependency coordinates to module
dependencies

• Help, non-exported packages of different modules collide!
@aalmiray | andresalmiray.com
What no one ever said
“Let’s use JPMS Layers to
tackle (some of) these issues”
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/ModuleLayer.html
@aalmiray | andresalmiray.com
Using the Layers API
@aalmiray | andresalmiray.com
https://github.com/
moditect/layrry/
Gunnar
Morling
Open Source Software
Engineer

@ RedHat

Java Champion

Lead of Debezium

Bean Validation 2.0 Spec Lead

morling.dev
@aalmiray | andresalmiray.com
Hello Layrry!
Layrry
JPMS
Launch!
YAML sucks!
TOML rocks!
Plugin Architectures
1 package org.moditect.layrry.platform;
2
3 /**
4 * Implementations get notified about the
5 * addition or removal of plug-in layers.
6 * Retrieved via the service loader API.
7 */
8 public interface PluginLifecycleListener {
9
10 void pluginAdded(PluginDescriptor plugin);
11
12 void pluginRemoved(PluginDescriptor plugin);
13 }
1 @Override
2 public void pluginAdded(PluginDescriptor plugin) {
3 ServiceLoader<MyService> services = ServiceLoader.load(
4 plugin.getModuleLayer(), MyService.class);
5
6 services.forEach(service -> {
7 // only process services declared by the added layer itself,
8 // but not from ancestor layers
9 if (service.getClass().getModule().getLayer() == layer) {
10 // process service ...
11 }
12 });
13 }
Parameterization
layrry-launcher-1.0-SNAPSHOT-all.jar 
—layers-config javafx.toml 
—properties versions.properties
@aalmiray | andresalmiray.com
Launch options
• Use the ready made launcher from the command line.

• Build your custom launcher.

• Or …
jbang layrry@moditect 
—layers-config javafx.toml 
—properties versions.properties
DEMO
@aalmiray | andresalmiray.com
Future
• Support remote configuration (?)

• Ready made binary distributions

• Distribution channels

• Github releases

• Homebrew (?)

•
@aalmiray | andresalmiray.com
Resources
• https://www.morling.dev/blog/introducing-layrry-runner-
and-api-for-modularized-java-applications/

• https://www.morling.dev/blog/plugin-architectures-with-
layrry-and-the-java-module-system/

• https://www.morling.dev/blog/class-unloading-in-layered-
java-applications/

• https://github.com/moditect/layrry/

• https://github.com/moditect/layrry-examples/
@aalmiray | andresalmiray.com

Building modular applications with JPMS and Layrry