Java Platform Module System( Java Modules)
Java modules was introduced in Java 9.
Module is all about structural changes in java application.
Before Java 9, the JDK was a monolithic set of packages, packaged in one jar file,
the rt.jar, which any java application would need to deploy alongwith it's own
code.
rt.jar:
rt.jar contains all of the compiled class files for the base Java Runtime
environment, as well as the bootstrap classes, which are the run time classes that
comprise the Java platform core API.
Module is a group of packages. But unlike jars, modules add another level of
encapsulation where all the packages may not be exposed to outside environment.
Also, an application can mention on what all modules they require for their
application.
Standard modules:
All of the modules in the Java SE are standard modules as defined by the JCP.
A standard module, may contain both standard and non-non standard API packages.
A standard package is prefixed with "java." or "javax.", like java.base ....
Non-standard modules:
The JDK: jdk APIs are specific to the JDK.
These APIs are in modules whose names start with a "jdk." prefix.
A non-standard module must not export any standard API packages.
examining modules from the command line:
java --list-modules
java --describe-module java.logging
jDeps: Java Class Dependency Analyzer
-m: module
jdeps --print-module-deps -m java.sql
jdeps --print-module-deps --module java.sql
jdeps --list-deps -m java.sql.rowset
jdeps --list-reduced-deps -m java.sql.rowset
Creating a Module in Java:
module-info.java
module myfirstmodule{
module com.lti.user{
In an application, there can be several modules, and each module contains precisely
one module-info.java
myfirstmodule
--src
--com.lti.user
---User.java
---Application.java
--com.lti.admin
--Admin.java
--module-info.java
mysecondmodule
--src
--com.cit.user
---Test.java
---App.java
--com.citi.admin
--Admin.java
--module-info.java
We can also package the above compilation output in a JAR(modular jar) file.
myfirstmodule.jar
--META-INF
--MANIFEST.MF
--com.lti.user
---User.class
---Application.class
--com.lti.admin
--Admin.class
--module-info.class
firstmodule
--src
--com.lti.greet
--Hello.java
--module-info.java
Non-modular java application:
C:\Program Files\jdk-16.0.2\bin\javaw.exe
-Dfile.encoding=Cp1252
-classpath "D:\OCP-NEW BATCH\OCP Demos\FirstModule\bin"
-XX:+ShowCodeDetailsInExceptionMessages com.lti.greet.Hello
Non-modular java applications run on "classpath" but modular java applications run
on "modulepath"
Module java application:
C:\Program Files\jdk-16.0.2\bin\javaw.exe
-Dfile.encoding=Cp1252
-p "D:\OCP-NEW BATCH\OCP Demos\TestModule\bin"
-XX:+ShowCodeDetailsInExceptionMessages
-m testmodule/com.lti.greet.Hello
-p: module path
-m: module name
-d: directory in which you want to place your class files. By default eclipse use
bin folder. IntelliJ, uses out folder.
javac -d bin src/com/lti/greet/Hello.java src/module-info.java
bin
--firstmodule
--com.lti.greet
--Hello.class
--module-info.class
java -p bin -m firstmodule/com.lti.greet.Hello
java -p bin --describe-module firstmodule
Create a modular jar:
jar --create --file MyModularJar.jar --main-class com.lti.greet.Hello -C bin/ .
running a jar file:
java -jar MyModularJar.jar
jdeps --module-path bin MyModularJar.jar
----------------------------------------------
Module created in project "Global":
module name: org.module.global
--src
--com.lti.app/Application.java
--com.lti.demo/Demo.java
--module-info.java{
exports com.lti.app;
exports com.lti.demo;
}
Module created in project "Client":
module name: org.module.client
--src
--com.lti.client/Client.java
--module-info.java{
require org.module.app
}
java -p bin --describe-module org.module.client
-------------------------------------------------------------------------------
org.module.base--------(required)---------->org.module.util-----------(required
transitive)---->org.module.global
export com.lti.util
exports com.lti.app
exports
com.lti.demo
Module created in project "Util":
module name: org.module.util
--src
--com.lti.util/MyUtilities.java
--module-info.java{
require transitive org.module.global
exports com.lti.util
}
Module created in project "Base":
module name: org.module.base
--src
--com.lti.base/BaseClient.java
--module-info.java{
require org.module.util
}
jdeps --module-path bin -m org.module.global
jdeps --module-path bin;"D:\OCP-NEW BATCH\OCP Demos\Global\bin" -m org.module.util
jdeps --module-path bin;"D:\OCP-NEW BATCH\OCP Demos\Util\bin";"D:\OCP-NEW BATCH\OCP
Demos\Global\bin" -m org.module.base
Friendly module: Qualified exports
exports com.lti.app to org.module.util,org.module.concrete;
Cyclic dependency is not allowed.
1. Direct cycle:
org.module.util----------->org.module.global
org.module.util<-----------org.module.global
2. Indirect cycle
org.module.util----------->org.module.global
org.module.base<-----------org.module.global
org.module.base------------>org.module.util
--------------------------------------------Services in
Modules-----------------------------------------------------------------
Project Name: Service
module1: org.module.servicemodule
com.lti.service/ServiceRegistry(interface)-->greetings()
module-info.java{
exports com.lti.service;
}
Project Name: ProviderOne
module2: org.module.providerone
com.lti.impl1/Serviceimpl1(class) which implements the ServiceRegistry
interface---->override the greetings method
module-info.java{
require org.module.servicemodule;
provides com.lti.service.ServiceRegistry
with com.lti.impl1.Serviceimpl1
}
Project Name: ProviderTwo
module3: org.module.providerone
com.lti.impl2/Serviceimpl2(class) which implements the ServiceRegistry
interface---->override the greetings method
module-info.java{
require org.module.servicemodule;
provides com.lti.service.ServiceRegistry
with com.lti.impl2.Serviceimpl2
}
Project Name: Consumer
module4: org.module.comsumer
module-info.java{
require org.module.servicemodule;
uses com.lti.service.ServiceRegistry
}
opens com.lti; //reflexive access
opens com.lti to org.module.testopen;
-------------------------------------------------
Quiz-------------------------------------------------------------------------------
Question 1:
Your application is packaged in myapp.jar and depends on a jar named datalayer.jar,
which in turn depends on mysql-connector-java-8.0.11.jar. The following packages
exist in these jars:
myapp.jar: com.abc.myapp
datalayer.jar: com.abc.datalayer
mysql-connector-java-8.0.11.jar: com.mysql.jdbc
You have decided to modularize your application even though datalayer and mysql
libraries are still not modularlized. Which of the following would be a valid
module-info for your app?
A. module abc.myapp{
requires com.abc.datalayer;
}
B. module abc.myapp{
exports com.abc.myapp;
}
C. module abc.myapp{
requires datalayer;
}
D.module abc.myapp{
requires datalayer;
requires mysql-connector-java;
}
E. module abc.myapp{
requires datalayer;
requires mysql-connector-java-0.0.11;
}
F. module abc.myapp{
requires com.abc.datalayer;
requires com.mysql.jdbc;
}
Question 2:
Identify correct statements about the module system of Java.
A. Only an application structured as modular can be run on a modular JDK.
B. Main goals of the module system are to improve security with strong
encapsulation and stability with reliable dependencies.
C. Code in modules and traditional JARs on the classpath cannot coexist in an
application.
D. Modules have concealed packages for internal use and exported packages for
shared code with other modules.
Question 4:
Which of the following are valid module definitions?
A.
//In file module.java:
module autos{
}
B.
//In file autos.java:
module autos{
}
C.
//In file module-info.java:
module autos{
}
D.
//In file module-info.java:
module cars{
exports com.car;
}
module trucks{
requires cars;
}
E.
//In file module-info.java:
module-info autos{
}
Question 6:
You are creating an acme.accounting module that depends on acme.math module and
makes its com.acme.accounting package available to all other modules. Which of the
following files correctly defines this module?
A. //In file module.java:
module acme.accounting{
requires acme.math;
exports com.acme.accounting;
}
B. //In file module.java:
module acme.accounting{
requires acme.math.*;
exports com.acme.accounting.*;
}
C. //In file module.java:
module acme.accounting{
requires acme.math;
exports com.acme.accounting.*;
}
D. //In file module-info.java:
module-info acme.accounting{
requires acme.math;
exports com.acme.accounting;
}
E. //In file module-info.java:
module acme.accounting{
requires acme.math;
exports com.acme.accounting;
}
Question 8:
Given:
module broker{
exports org.broker.api;
}
The broker module contains org.broker.api.Installer interface, which is implemented
by com.foo.AppInstaller class of com.foo module.
Which of the following is a valid module definition for com.foo module?
A. module com.foo{
exports broker;
}
B. module com.foo{
provider broker;
}
module com.foo{
requires broker;
provides org.broker.api;
}
C. module com.foo{
requires broker;
exports com.foo;
provides org.broker.api.Installer with com.foo.AppInstaller;
}
D. module com.foo{
exports com.foo;
provides org.broker.api.Installer with com.foo.AppInstaller;
}
Question 9:
Given the following contents of module-info.java,
module enthu.finance{
exports com.enthu.Reports;
requires enthu.utils;
}
Select correct statements.
A. Module name is finance.
B. com.enthu.Reports is the name of the class that this module exports.
C. This module depends on enthu.utils package.
D. This file must be present in enthu.finance directory if the source code is to be
compiled using the --module-source-path option.
E. Other modules that depend on this module will be able to access
com.enthu.Reports package as well as enthu.utils package.
MyApp
|
|-org.lti
|
|--org.lti.myfirstmodule
| src
| --com.lti/App.java
| --com.lti.test/App2.java
| --module-info.java
|
|-- org.lti.mysecondmodule
src
--com.lti/App.java
--com.lti.test/App2.java
--module-info.java
-m myfirstmodule ---------> --moudule-source-path org.lti