Migration from Non-Modular to Modular Code - 13.11 | 13. Java Modules and the JPMS (Java Platform Module System) | Advance Programming In Java
Students

Academic Programs

AI-powered learning for grades 8-12, aligned with major curricula

Professional

Professional Courses

Industry-relevant training in Business, Technology, and Design

Games

Interactive Games

Fun games to boost memory, math, typing, and English skills

Migration from Non-Modular to Modular Code

13.11 - Migration from Non-Modular to Modular Code

Enroll to start learning

You’ve not yet enrolled in this course. Please enroll for free to listen to audio lessons, classroom podcasts and take practice test.

Practice

Interactive Audio Lesson

Listen to a student-teacher conversation explaining the topic in a relatable way.

Identifying Modules

🔒 Unlock Audio Lesson

Sign up and enroll to listen to this audio lesson

0:00
--:--
Teacher
Teacher Instructor

Today, we're discussing how to identify and isolate modules in your current codebase. This is crucial for a successful migration to JPMS.

Student 1
Student 1

What does it mean to isolate a module?

Teacher
Teacher Instructor

Good question! Isolating a module means identifying a self-contained group of packages that can work together without unnecessary dependencies on other parts of the code. It enhances encapsulation.

Student 2
Student 2

How do we know which packages should be grouped?

Teacher
Teacher Instructor

You should look for related functionalities. For example, all database-related packages can be part of a `database` module. A mnemonic to remember this is 'R.E.L.A.T.E.': Related Elements Linked As a Team Effectively.

Student 3
Student 3

So are we looking for cohesion within the packages?

Teacher
Teacher Instructor

Exactly! Cohesion is vital. At the end of this conversation, remember: identify, isolate, and group related packages.

Creating module-info.java

🔒 Unlock Audio Lesson

Sign up and enroll to listen to this audio lesson

0:00
--:--
Teacher
Teacher Instructor

Now that we have identified our modules, let's talk about creating the `module-info.java` file. This file acts as our module descriptor.

Student 4
Student 4

What goes into this file?

Teacher
Teacher Instructor

It includes the module name, the packages it exports, and any modules it requires. You can think of it as the module's 'business card'.

Student 1
Student 1

Can you show us an example?

Teacher
Teacher Instructor

"Absolutely! For instance:

Moving Libraries to Module Path

🔒 Unlock Audio Lesson

Sign up and enroll to listen to this audio lesson

0:00
--:--
Teacher
Teacher Instructor

Next, let's move on to the libraries—specifically how to transition them to the module path.

Student 3
Student 3

What challenges might I face in this step?

Teacher
Teacher Instructor

You might encounter issues with libraries that weren't designed for JPMS. It's important to check compatibility.

Student 4
Student 4

How do I know if a library is compatible?

Teacher
Teacher Instructor

Look for libraries that provide modular JARs or verify compatibility in their documentation. A quick tip: a library designed for JPMS will usually mention it clearly.

Student 1
Student 1

So how do I actually move them?

Teacher
Teacher Instructor

Adjust your build path to include these libraries in the module path instead of the classpath. Remember: 'M.P. for L.P.' - Move Packages to Library Path!

Using Directives in module-info.java

🔒 Unlock Audio Lesson

Sign up and enroll to listen to this audio lesson

0:00
--:--
Teacher
Teacher Instructor

Let's explore the directives you’ll use in the `module-info.java` file: `requires`, `exports`, and `opens`.

Student 2
Student 2

What does each directive do?

Teacher
Teacher Instructor

`requires` denotes dependencies, `exports` allows access to certain packages, and `opens` grants reflective access. You can remember this sequence as 'R.E.O.' — Requires, Exports, Opens.

Student 3
Student 3

Will everything need to be exported?

Teacher
Teacher Instructor

Not necessarily. Only export packages that are meant to be used by other modules. Think of it as deciding which doors to open in your house.

Student 4
Student 4

What about the `opens` directive?

Teacher
Teacher Instructor

Use `opens` for packages that need reflection, like when using frameworks. Remember: ‘O’ is for ‘Openness’ in reflective programming.

Refactoring for Reflection

🔒 Unlock Audio Lesson

Sign up and enroll to listen to this audio lesson

0:00
--:--
Teacher
Teacher Instructor

The last focus of our session is refactoring your code for reflective access using the `opens` directive.

Student 1
Student 1

Why do we need to refactor for reflection?

Teacher
Teacher Instructor

Some libraries rely on reflection to implement features. Without `opens`, they can't access those internal packages.

Student 2
Student 2

How do I know which packages need `opens`?

Teacher
Teacher Instructor

Identify the packages used by the reflective libraries. Document this to ensure transparency. The key phrase here is 'Open Up for Access!'

Student 3
Student 3

Will this affect performance?

Teacher
Teacher Instructor

It can slightly affect performance due to reflection overhead but is balanced by the flexibility it offers.

Introduction & Overview

Read summaries of the section's main ideas at different levels of detail.

Quick Overview

This section outlines the steps to migrate Java code from a non-modular structure to a modular one using the Java Platform Module System (JPMS).

Standard

The migration from non-modular to modular code involves identifying modules, creating module descriptors, moving libraries to the module path, and refactoring code for reflection. These steps enhance modular organization and code manageability in Java applications.

Detailed

Migration from Non-Modular to Modular Code

Migrating existing Java applications from a non-modular to a modular architecture using the Java Platform Module System (JPMS) is crucial for leveraging the advantages of modularization. The primary steps to achieve this migration include:

  1. Identify and Isolate Modules: Analyze the existing codebase to determine logical groupings of related packages and functionalities that can be encapsulated as modules.
  2. Create module-info.java: For each identified module, create a module-info.java file that defines the module's name, its dependencies (using the requires directive), and the packages it exports (using the exports directive).
  3. Move Libraries: Transition third-party libraries and dependencies from the classpath to the module path, ensuring they are correctly referenced in the module-info.java files where necessary.
  4. Use Directives: Utilize the requires, exports, and opens directives to control access and encapsulation based on the module's requirements.
  5. Refactor for Reflection: Update the code that relies on reflection to access internal elements of the module—these must be opened explicitly using the opens directive to allow reflective access.

Completing these steps not only facilitates the migration process itself but also sets a foundation for improved scalability, maintainability, and security of Java applications moving forward.

Youtube Videos

Module System, Migration to JDK 11, Modularizing Your Applications with @Sander_Mak
Module System, Migration to JDK 11, Modularizing Your Applications with @Sander_Mak
Overview of the Java Memory Model
Overview of the Java Memory Model

Audio Book

Dive deep into the subject with an immersive audiobook experience.

Identifying Modules in Your Codebase

Chapter 1 of 5

🔒 Unlock Audio Chapter

Sign up and enroll to access the full audio experience

0:00
--:--

Chapter Content

  1. Identify and isolate modules in your codebase.

Detailed Explanation

The first step in migrating from non-modular to modular code is to look at your existing code and figure out which parts can be grouped together as modules. A module should contain related packages and classes that work towards a common purpose. This helps in organizing the code and defines boundaries for functionality.

Examples & Analogies

Think about a kitchen where different utensils are stored in separate drawers. If you combine them all into one big drawer, it becomes hard to find what you need. By identifying modules, you are effectively organizing your kitchen drawers, ensuring that similar items are grouped together, making it easier to access what you need.

Creating the module-info.java File

Chapter 2 of 5

🔒 Unlock Audio Chapter

Sign up and enroll to access the full audio experience

0:00
--:--

Chapter Content

  1. Create module-info.java for each module.

Detailed Explanation

After identifying the modules, the next step is to create a module-info.java file for each module. This file describes the module, including what it requires from other modules and what it exports to the outside world. This is crucial since it serves as a contract for your module’s interactions.

Examples & Analogies

Imagine that your module is like a store with a sign outside (the module-info.java file), which tells customers what products (functionalities) it offers and which suppliers (dependencies) it relies on. Just as a store needs a clear sign for customers, your module needs a module-info.java to clearly define its role.

Moving Third-Party Libraries

Chapter 3 of 5

🔒 Unlock Audio Chapter

Sign up and enroll to access the full audio experience

0:00
--:--

Chapter Content

  1. Move third-party libraries to the module path.

Detailed Explanation

In this step, you will take any third-party libraries your code relies on and ensure they are added to the module path instead of the classpath. This means that these libraries need to be modularized or recognized as modules by the Java compiler and runtime.

Examples & Analogies

Consider a library that lends books. If you want to build an exclusive collection (module path), you cannot include non-member books (libraries not on the module path). Instead, you need to have all your books categorized properly to maintain consistency and avoid confusion.

Using Requires, Exports, and Opens

Chapter 4 of 5

🔒 Unlock Audio Chapter

Sign up and enroll to access the full audio experience

0:00
--:--

Chapter Content

  1. Use requires, exports, opens as needed.

Detailed Explanation

After moving the libraries, you need to tell each module which other modules it requires (dependencies), which packages it exports (accessible to other modules), and which packages need to be opened for reflection. This step is key for maintaining clean interactions between modules and ensuring they can function together seamlessly.

Examples & Analogies

Think of this step like setting up communication protocols between different departments in a company. You need to specify who can talk to whom (requires), what information can be shared (exports), and what confidential discussions (opened packages) can take place to ensure smooth cooperation.

Refactoring Reflective Access

Chapter 5 of 5

🔒 Unlock Audio Chapter

Sign up and enroll to access the full audio experience

0:00
--:--

Chapter Content

  1. Refactor reflective access with opens.

Detailed Explanation

Finally, if any part of your code relies on reflection (a feature in Java that allows inspection of classes, interfaces, fields, and methods at runtime), you'll need to refactor this access. This is done by using the opens directive in your module-info.java file to allow specific packages to be accessed reflectively.

Examples & Analogies

This step is like opening a restricted area in a building for certain authorized personnel (like maintenance workers) to access. By using the opens directive, you're specifying which areas can be accessed under specific circumstances, thereby maintaining overall security while allowing necessary access.

Key Concepts

  • Identifying Modules: The process of analyzing code to group related packages into modules.

  • module-info.java: A descriptor file defining module properties.

  • Requires Directive: Specifies which modules are dependencies.

  • Exports Directive: Makes specific packages available to other modules.

  • Opens Directive: Allows reflective access to specific packages.

Examples & Applications

Example of module-info.java for a simple application module:

module com.example.myapp {

requires com.utils;

exports com.example.myapp.api;

}```

To refactor for reflection, you might use:

opens com.example.myapp.internal;``` to allow reflective libraries to access internal packages.

Memory Aids

Interactive tools to help you remember key concepts

🎵

Rhymes

To migrate your code with great ease,

📖

Stories

Imagine a library with many rooms. Each room is a package. You need to mark which rooms are open to visitors (exports) and which rooms are only for staff (internal use). This is what module-info.java does for your code.

🧠

Memory Tools

Remember R.E.O: Requires, Exports, Opens - it helps you recall the order of directives in module-info.java.

🎯

Acronyms

I.I.G.

Identify

Isolate

Group - the steps to take when starting module migration.

Flash Cards

Glossary

moduleinfo.java

A Java file that acts as a module descriptor, specifying module details such as dependencies and exported packages.

JPMS

Java Platform Module System, introduced in Java 9, enabling modularization of Java applications.

requires

A directive in the module-info.java that specifies dependencies on other modules.

exports

A directive that allows specific packages to be made accessible to other modules.

opens

A directive that allows reflective access to the packages by other modules.

nonmodular code

Code that does not use the module system to structure dependencies and organization.

module path

A runtime path for locating modules, contrasting with the classpath used for traditional Java applications.

Reference links

Supplementary resources to enhance your learning experience.