Beginning the migration

Let's go through the migration process by working on the sample shopping bag application. It's a simple app that contains three classes--one to read user input, one to provide a shopping bag functionality, and one class with a main method to drive execution--iteratively taking in user input, adding it to the shopping bag, and then printing the contents of the bag. The application has a dependency on the commons collections JAR file for the Bag data structure. It also calls the Java logging API to log the start and end times to the console.

The shopping bag application has code that is referred to as a monolith. That is, all the code that forms the app is in one code base. This is really a simplification, and does not represent a real-world application that could span multiple projects and have different build artifacts that are bundled together. We'll keep things simple and run through the migration process with the simplified monolithic code base first and then expand it to a multi-project setup.

We are starting with the code in the 01-legacy-app folder. The application code is in the src folder and the commons collections JAR in the lib folder:


The first step to modularizing this application is to create one big module that wraps around the entire application. We've run this application in the classpath in Chapter 10, Preparing Your Code for Java 9. The platform helped us there by creating an unnamed module that housed all of our code, which was an automatic process. This time, we'll do this ourselves by creating a module for our application called packt.shoppingbag.

First, just like before, let's assign a module source folder where the source of all the modules resides. You can either create a new folder or use the existing src folder. I'll choose the latter. In the src folder, create a module room folder, packt.shoppingbag, and a module-info.java file within it:

    module packt.shoppingbag { 
    } 

It's just an empty module descriptor for now. We'll get back to this in a bit.

Now that we have a module root, you can move the entire source (with the package name folder hierarchy) into the module root folder. The source code in the 11-migrating-application/02-migrating-to-one-module folder represents this state of the code base:


What we have now is far from a modular Java application. However, it does technically have one module. So, the way to compile and execute this application needs to be similar to what we've done so far in this book. That is, use the module source path argument for the source location containing the module root and the module path argument to point to the location of the compiled modules.

Let's try compiling this application. We'll first create a folder called out to contain the compiled classes:

$ mkdir out

Here's the javac command we've used all along:

$ javac --module-source-path src -d out $(find . -name '*.java')

If you run this, you'll get the following error:

$ javac --module-source-path src -d out $(find . -name '*.java')
./src/packt.shoppingbag/module-info.java:3: error: module not found: commons.collections4
requires commons.collections4;
^
1 error

The compiler is unable to find the commons collections dependency. Makes sense! The JAR in the lib folder and we never told the compiler about it. Now, can we add this JAR to the class path and compile again?

$ javac --module-source-path src -cp lib/commons-collections4-4.1.jar -d out $(find . -name '*.java')
./src/packt.shoppingbag/module-info.java:3: error: module not found: commons.collections4
requires commons.collections4;
^
1 error

Nope, that won't work either. Why is that? Here's a picture of the application we have now:

We've moved the application code into the module path, but the library (in our case, a single JAR file) still exists in the classpath. And, since it is in the classpath, it is a part of the automatically created unnamed module. We've already seen how the unnamed module reads all resolved modules by default. Thus, any code in the unnamed module can access types in the module path. This is what we did in Chapter 10, Preparing Your Code for Java 9:

However, what we are trying to do here is the other way round. We want a module in the module path to access types from the unnamed module, and there's the problem. It turns out that no other module can read the unnamed module!

This is an intentional restriction. Every module needs to meet the requirements of strong encapsulation and reliable configuration. If a module were to read the class path, we'd basically be tossing reliable configuration out of the window! Since the class path does not have reliable configuration, there's no way the platform can verify if the module has everything it needs. So, preventing explicit Java 9 modules from accessing the classpath is a Good Thing™.

It does cause a major problem with migration though. Moving code from the class path to the module path is taking it down a one-way street. Once the code is crossed over to the module path, it cannot access anything from the class path. It's not so much an issue for your application code. Like we've seen, you can take your entire code base and put it in a giant named module, like we did with the shopping bag app. And now, none of your code is in the classpath. Great! However, what about libraries? Almost every Java application has third-party libraries and frameworks that are mostly JARs pulled in from the internet and bundled into the classpath. Since we don't control or maintain the library code, we cannot put their code in a module and wrap them with a module descriptor. So, until the authors of your libraries get to migrate their code to Java 9, you are stuck with non-modular libraries. How can your types access them? Do you have to hold off on modularizing your code until the very last library you use has its code migrated to Java 9?

Thankfully, that's not the case. The platform helps, once again, with the ability to create modules from JARs automatically. These modules are called automatic modules.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.181.57