In this video, Nick Maiorano shows how to structure the hierarchy and modules, packages, and classes within JPMS, as well as the role of the newly introduced module path.
I'm going to build a simple Java application that expresses different types of dependencies. I'll continue to use the red30tech car parts manufacturing example and I'll build upon it. The focus of this exercise will be on the modular aspects of the application rather than the application itself. I'll keep the code as short as possible so that the focus can stay on modularity. I won't be using any Java based editors because I want to focus on the command line tools that are important to Java modularity.
Keep in mind that different editors will use slightly different structures, but the concepts remain the same. JPMS introduces the concept of a module path. As modularity becomes a first class citizen of Java, it's only natural that there exists something at runtime that could structure things in terms of modules. The module path tells the compiler and runtime where to find the modules needed to compile and run the application. The module path is to modules what a class path is to classes.
Developers writing modular code in Java 9 must structure to directory hierarchy in the file system in the same way as its represented in modules and packages. The directory hierarchy must match module and package hierarchy. This means that package hierarchies continue to have the same structure as always, but JPMS now imposes structure in which each module is in a separate directory hierarchy, no more monolithic code bases. In this example, the module is com red30tech movement.
This means that the module directory must have the same name, plus the module info file must be placed at the root of the module. Both of these are requirements set by JPMS. Violating these rules will result in a compilation error. As usual, there is the package hierarchy, in this case, com red30tech movement plus its three sibling directories, rubberpart, API, and metalpart. When this structure is compiled, it will create a parallel hierarchy like this.
The module's entire hierarchy is kept intact to preserve the structural integrity of runtime and this is in keeping with JPMS's objectives. The hierarchy is stored under the mods directory, this is a convention, not a strict requirement. At runtime, the module path will inform the Java platform where to find the modules and classes within the module. It's specified as a parameter on the Java command line. For a modular code written with Java 9 modules, the role of the module path supersedes that of the class path.
The class path is still supported in Java 9, but it's generally meant to be used for legacy code and to maintain backward compatibility. Otherwise, the module path is mandatory. The module path goes much further in providing structural integrity than does the class path. For example, there can only be one instance per module on the module path. The runtime will reject a module path containing duplicate modules. The key takeaway is that the member classes of com red30tech movement will be taken as a whole and there is no way to use portions of classes found in one directory and combining with classes in another directory.
JPMS uses the module path in conjunction with the module info to determine the member classes of a module. There is no metadata stored within the class itself that stamps module membership, unlike packages. In fact, it is the module info itself that acts as the metadata holder for all classes within the module. If the module info class file is removed, the Java platform will fail to start up because it won't be able to locate the classes within the module.
For small applications, it's possible to make do with just one module and that's a design decision that needs to weigh design complexity versus business requirements. For applications needing to be a little bit more modular, additional modules can be created with their own separate hierarchy. Suppose the red30tech car company also builds axles that need to be combined with wheels. It could then have this hierarchy. Compiling it will result in this parallel directory structure.
The module path can aggregate many modules. In a full blown modular application, for example, you can have many modules and the module path is what allows the Java runtime to find them all. Although this is outside your preview of JPMS, you could think of modules as being independent aisles of code with their own code bases, maintained by their own teams, and delivered according to their own schedules. JPMS doesn't impose any particular structure on soft routines, but it certainly enables this kind of thinking.
In this course, instructor Nick Maiorano breaks down this complexity by explaining what modularity is all about, how Java has adopted modularity and how to start using to build better quality applications.
- What is modularity?
- The five pillars of modularity
- Modularity in the real world
- JPMS concepts and syntax
- Designing and implementing a modular structure
- Compiling, packaging and running modular applications
- Using the dependency checking tools
- Creating custom runtime images
- Managing backward compatibility with classes and modules
- Explicit, unnamed, and automatic modules
- JPMS tips and recommendations