Overview

We have discussed Java 9 Modularity and Module System. Also we have discussed How to create first Module in Java 9 using eclipse. Here we will discuss in detail of Module Descriptor and different directives.

As we mentioned, a module must provide a module descriptor—metadata that specifies the module’s dependencies, the packages the module makes available to other modules, and more. A module descriptor is the compiled version of a module declaration that’s defined in a file named module-info.java. Each module declaration begins with the keyword module, followed by a unique module name and a module body enclosed in braces, as in

The module declaration’s body can be empty or may contain various module directives, including requires, exports, provides…with, uses and opens.

Let’s understand one by one with examples.

1. requires

A requires module directive specifies that this module depends on another module—this relationship is called a module dependency. Each module must explicitly state its dependencies. When module A requires module B, module A is said to read module B and module B is read by module A. To specify a dependency on another module, use requires, as in:

requires modulename;
Example

Let’s take an example, We have two modules: A and B. Module A is used to display a message using a class called DisplayMessage. Module B usages services of Module A to display the messages.

Project Structure
Project Structure

Project A Module Descriptor :

Project B Module Descriptor :

Here, we are specifying that module B requires the services of A,

DisplayMessage.java

PostMessage.java

Output

Hello World !!

There is also a requires static directive to indicate that a module is required at compile time, but optional at runtime. This is known as an optional dependency.

2. requires transitive

To specify a dependency on another module and to ensure that other modules reading your module also read that dependency—known as implied readability—use requires transitive as in:

requires transitive modulename;
Example

Let’s continue with our example, with Module A and B, Let’s have a third module C which is depends on Module B. So dependencies are like C -> B -> A .

We have modified PostMessage class from Module B which returns the DisplayMessage object by calling getDisplayMessage() method, Which shows Module B is dependent on A and any other module depends on Module B also needs access of Module A.

Here making a dependency of module B in C will not include dependency of module A, For that, we need to change module descriptor for module A in module B from requires to requires transitive.

Project Structure
Project Structure

Project A Module Descriptor :

Project B Module Descriptor :

Project C Module Descriptor :

PostMessage.java

RetrieveDisplayMessage.java

Output

Hello World !!

3. exports and exports…to

An exports module directive specifies one of the module’s packages whose public types (and their nested public and protected types) should be accessible to code in all other modules. An exports…to directive enables you to specify in a comma-separated list precisely which module’s or modules’ code can access the exported package—this is known as a qualified export.

As per example, To get access of module A in B, module descriptor of the module A having export of package com.codenuclear.a

4. open, opens and opens…to

A key motivation of the module system is strong encapsulation. Before Java 9, reflection could be used to learn about all types in a package and all members of a type—even its private members—whether we wanted to allow this capability or not. Thus, nothing was truly encapsulated.

By default, a type in a module is not accessible to other modules unless it’s a public type and we export its package. We expose only the packages which we want to expose. With Java 9, this also applies to reflection.

4.1 Allowing Runtime-Only Access to a Package

An opens module directive of the form

opens package

indicates that a specific package’s public types (and their nested public and protected types) are accessible to code in other modules at runtime only. Also, all of the types in the specified package (and all of the types’ members) are accessible via reflection.

Example

In the above example, Lets say method getDisplayMessage() of class PostMessage is made private in the next version of module B, However, module C is using it which is not going to be accessible with latest version of module B. To avoid this problem Module B can open that package and same can be accessible from module C with reflection.

Project B Module Descriptor :

PostMessage.java

Have you noticed scope of the getDisplayMessage() is changed from public to private.

RetrieveDisplayMessage.java

Output

Hello World !!
4.2 Allowing Runtime-Only Access to a Package By Specific Modules

An opens…to module directive of the form

opens package to comma-separated-list-of-modules

indicates that a specific package’s public types (and their nested public and protected types) types are accessible to code in the listed module(s) at runtime only. Also, all of the types in the specified package (and all of the types’ members) are accessible via reflection to code in the specified modules.

4.3 Allowing Runtime-Only Access to All Packages in a Module

If all the packages in a given module should be accessible at runtime and via reflection to all other modules, you may open the entire module, as in

5. Restricted Keywords

The keywords exports, module, open, opens, provides, requires, to, transitive, uses and with are restricted keywords. They’re keywords only in module declarations and may be used as identifiers anywhere else in your code.

We mentioned that there is also a requires static module directive. Of course, static is a regular keyword.

That’s all for Module Descriptor and Directives in Java 9, Hope you liked it. Keep Learning and Sharing 🙂 !!

It's good to share...Share on FacebookTweet about this on TwitterShare on LinkedInPin on PinterestShare on Google+Email this to someone

Leave a Reply

Your email address will not be published. Required fields are marked *