Java Modules Tutorial

JPMS (Java Platform Module System) is the major enhancement in Java 9. It is also known as Project Jigsaw. In this Java 9 modules example, we will learn about modules (in general) and how your programming style will change in future when you will start writing modular code.

Table of Contents

What is a Module
Introduction to Java 9 Modules
How to Write Modular Code
Summary

What is a Module in General

In any programming language, modules are (package-like) artifacts containing code, with metadata describing the module and also its relation to other modules. Ideally, these artifacts are recognizable from compile-time all the way through run-time. Any application generally is combination of multiple modules which work together to perform the business objectives.

In terms of application architecture, a module shall represent a specific business capability. It should be self-sufficient for that capability, and should expose only interfaces to use the module functionality. To complete its tasks, it may be dependent on other modules, which it should declare explicitly.

So, in short, a module should adhere to three core principles –

  • Strong Encapsulation

    Encapsulation means to hide implementation details, which are are not essential to know to use the module correctly. The purpose is that encapsulated code may change freely without affecting users of the module.

  • Stable Abstraction

    Abstraction helps to expose module functionality using interfaces i.e. public APIs. Anytime, you want to change the business logic or implementation inside module code, changes will be transparent to the module users.

  • Explicit dependencies

    Modules can be dependent on other modules as well. These external dependencies must be part of the module definition itself. These dependencies between modules are often represented as graphs. Once you see the graph at application level, you will have better understanding of the application’s architecture.

Introduction to Java 9 Modules

Before java 9, you had ‘packages‘ to group related classes as per business capabilities. Along with packages, you had ‘access modifiers‘ to control what will be visible and what will be hidden to other classes or packages. It has been working great so far. Java has strong support for encapsulation and abstraction.

But, explicit dependencies is where things start to fall apart. In java, dependencies are declared with ‘import‘ statements; but they are strictly ‘compile time’ constructs. Once code is compiled, there is no mechanism to clearly state it’s runtime dependencies. In fact, java runtime dependency resolution is so much problematic area that special tools have been created to fight this problem e.g. gradle or maven. Also, few frameworks started bundling their complete runtime dependencies as well e.g. Spring boot projects.

With new Java 9 modules, we will have better capability to write well-structured applications. This enhancement is divided into two area:

  1. Modularize the JDK itself.
  2. Offer a module system for other applications to use.
Java 9 Module System has a “java.base” Module. It’s known as Base Module. It’s an Independent module and does NOT dependent on any other modules. By default, all other modules dependent on “java.base”.

In java 9, modules helps you in encapsulating packages and manage dependencies. So typically,

  • a class is a container of fields and methods
  • a package is a container of classes and interfaces
  • a module is a container of packages

You will not feel any major difference between normal code and modular code if you don’t know the specific things to look for. e.g.

  1. A module is typically just a jar file that has a module-info.class file at the root.
  2. To use a module, include the jar file into modulepath instead of the classpath. A modular jar file added to classpath is normal jar file and module-info.class file will be ignored.

How to Write Modular Code

After reading all above concepts, let’s see how modular code is written in reality. I am using Netbeans IDE because it has good early support of Java 9 (as of today).

Create Java Modular Project

Create new modular project. I have created with name JavaAppOne.

Create Java Modular Project
Create Java Modular Project
Create Java Modular Project - Step 2
Create Java Modular Project – Step 2

Create Java Modules

Now add one or two modules in this project.

Create New Module
Create New Module

I have added two modules helloworld and test. Let’s see their code and project structure.

Java 9 Modules Project Structure
Java 9 Modules Project Structure

/helloworld/module-info.java

module helloworld {
}

HelloWorldApp.java

package com.howtodoinjava.demo;

public class HelloWorldApp {
    public static void sayHello() {
        System.out.println("Hello from HelloWorldApp");
    }
}

/test/module-info.java

module test {
}

TestApp.java

package com.test;

public class TestApp {
    public static void main(String[] args) {
        //some code
    }
}

So far, modules are independent. Now suppose, we want to use HelloWorldApp.sayHello() method in TestApp class. If you try to use the class without importing the module, you will get compile time error “package com.howtodoinjava.demo is not visible”.

Export Packages and Import Module

To be able to import HelloWorldApp, you must first export ‘com.howtodoinjava.demo’ package from helloworld module and then include helloworld module in test module.

module helloworld {
    exports com.howtodoinjava.demo;
}

module test {
    requires helloworld;
}

In above code, requires keyword indicates a dependency and exports keyword identifies the packages which are available to be exported to other modules. Only when a package is explicitly exported, it can be accessed from other modules. Packages inside a module that are not exported, are inaccessible from other modules by default.

Now you will be able to use HelloWorldApp class inside TestApp class.

package com.test;

import com.howtodoinjava.demo.HelloWorldApp;

public class TestApp {
    public static void main(String[] args) {
        HelloWorldApp.sayHello();
    }
}

Output:

Hello from HelloWorldApp

Lets look at the modules graph a well.

Module Graph
Module Graph
From Java 9 onwards, public means public only to all other packages inside that module. Only when the package containing the public type is exported, can it be used by other modules.

Summary

Modular applications have many advantages, which you appreciate even more, when you come across applications having non-modular codebase. You must have heard terms like “spaghetti architecture” or “messy monolith“. Modularity is not a silver bullet, but it is an architectural principle that can prevent these problems to a high degree when applied correctly.

With JPMS, Java has taken a big step to be a modular language. Whether it is right or wrong decision, only time will tell. It will be interesting to see, how 3rd party libraries and frameworks adapt and use the module system. And how it will impact the development work, we do everyday.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

1 thought on “Java Modules Tutorial”

  1. Hi Lokesh,

    Nice to see that you have started to come up with the tutorials on Java 9.
    The tutorial is good as a starter.
    I have not downloaded Netbeans for JDK9 support will give it a try soon.
    I was just going through the example to get the concept.
    I would suggest you to elaborate a bit more as how to export Module and import packages.

Comments are closed.

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.