Introduction
In this tutorial, we are going to learn how to create a Java module by hand.
Goals
At the end of this tutorial, you would have learned:
- What a
module-info.java
file is. - How to compile a module.
- Describing a module.
Prerequisite Knowledge
- Basic Java.
- Basic command-line interface.
Tools Required
- A CLI shell, such as
Command Prompt
for Windows,Terminal
for Mac, orBash
for Linux. - JDK 9+ path/environment variables already setup.
Concept Overview
Java Module is an abstraction on top of packages that allows for more fine-grained encapsulation.
In the module-info.java
file that defines every module, we can restrict the module’s dependencies, the packages that it exports, services that it consumes or offers, and whether it allows reflection.
The Bank Example
In order to see the concept of modules in action, we will create an example module. For learning purposes, we will not be using an IDE at all in this tutorial.
Let us assume that we are writing software for a bank. This bank has a software engineering team responsible for security.
The module that the security team creates is responsible for:
- Biometrics(information).
- Vault(security).
To give you a rough idea, later on, we are going to create the following modules and packages:
module: com.bank.security
package: com.bank.security.biometrics
package: com.bank.security.vault
The Security Module
First we will start with creating the security module.
-
Create a folder called
example
. This is where all of our modules live. -
Under example, create the following directories(recursively):
a.com/bank/security/biometrics
b.com/bank/security/vault
-
Under
com/bank/security
, create amodule-info.java
file. This file contains the definitions for yourcom.bank.security
module. You do not have to understand this file for now. I will explain it in the next section.module com.bank.security { }
-
Under biometrics, create a
Fingerprint.java
file. The file only needs two lines, a package declaration and an empty class.package com.bank.security.biometrics; public class Fingerprint {}
-
Under vault, create a
Guard.java
file. This file also does not contain anything significant.package com.bank.security.vault; public class Guard {}
Your directory tree should now look like this
.
└── example
└── com
└── bank
├── security
│ ├── biometrics
│ │ └── Fingerprint.java
│ ├── module-info.java
│ └── vault
│ └── Guard.java
The module-info.java File
At the minimum, a module-info.java
file must include the module name. The module name is declared right after the module keyword.
module com.bank.security
There are four types of modules.
- System modules: modules that came with the JDK.
- Automatic modules: regular jar files that are added to the module path(not the same as class path)
- Unnamed modules: a catch-all module that includes every jar file on the class path.
- Application modules: modules with the
module-info.java
file that application developers can create.
The com.bank.security
module that we just created is an example of an application module.
Compiling the Security module
To compile the security module, we would navigate back to the directory before the example directory, and use the below javac command:
javac -d compiled example/com/bank/security/biometrics/Fingerprint.java example/com/bank/security/vault/Guard.java example/com/bank/security/module-info.java
You should now see a directory named compiled
that contains compiled class files, including the module-info.class
.
The compiled directory should look like the tree below.
├── compiled
│ ├── com
│ │ └── bank
│ │ └── security
│ │ ├── biometrics
│ │ │ └── Fingerprint.class
│ │ └── vault
│ │ └── Guard.class
│ └── module-info.class
The exports Directive
Let us try to apply a common module directive: exports
. Modify the module-info.java
file and add the exports
directive.
module com.bank.security {
exports com.bank.security.biometrics;
}
This exports
directive allows any other module to read the biometrics package. Without it, other modules would not be able to use the biometrics
package normally.
Packaging a module
Next we will package our compiled module into a jar file.
-
Make a directory called
modules
. This is where we will place the packaged jar. -
Run the command below to package everything under the compiled directory into a jar.
jar -cvf modules/com.bank.security.jar -C compiled/ .
If you navigate to the modules directory, you will see the com.bank.security.jar
file.
Describing a module
Lastly, we will use a java
command to describe our module definitions.
java -p modules --describe-module com.bank.security
After running the above command, you will see the information below.
exports com.bank.security.biometrics
requires java.base mandated
contains com.bank.security.vault
The exports line indicates the package biometrics that we have exported earlier.
The requires line indicates that our module depends on the java.base
module. All Java modules implicitly require java.base
.
The contains line lists a package that is not exported at all, so this package is only usable to code inside the same module, under normal circumstances.
Solution Code
The whole project zip file can be downloaded here https://github.com/dmitrilc/DaniWebModule
Summary
We have learned how to create our own custom Java module in this tutorial. I skipped the IDE because I believe that compiling by hand is the best way to learn modules.