Firstly, thanks a lot for being here and congratulations on writing a book on such non-trivial topic.
I have more experience with pre-modular Java versions. However, when I look at Jigsaw it seems to me that biggest beneficent will be library providers or some IOT applications that care about minimizing the application size.
My question is: if you're developing a regular Java application using e.g. Spring Framework or a microservices-based application using Spring Boot then how can you benefit from the modular system?
Let's imagine one would really like to get his hands on the modularity and needs to convince the CTO that it's worth the investment in time.
How would you play this game? :-)
that's a great question to get started. 👍 Here are three benefits you can expect if your entire code base and your dependencies are modularized:
Reliable configuration helps you keeping your build intact. Missing dependencies? Duplicate dependencies? Shadowed classes? The module system will let you know.
Strong encapsulation prevents you from accidentally relying on your dependencies' internal APIs and helps you to conscientiously structure your own code for better maintainability.
module-info.java is a condensed view of your module, making it easy to review and analyze your project's real-life architecture (see this article for a little more detail on that).
None of these are mind-blowing features and they're much less exiting than, say, lambda expressions. That's because the module system is not so much a new tool as it's a safety belt and much of its value is not in making you faster, but in managing risk. That's less fun and because its benefit is in preventing rare, but costly problems, the value it provides is basically impossible to measure.
All of that said, I think it's absolutely worth it. Once an application is modules-only, the module system requires very little attention, so the running cost is really low. (How to get to that state is a different story, though.)
However, when I look at Jigsaw it seems to me that biggest beneficent will be library providers or some IOT applications that care about minimizing the application size.
That would be the new command line tool jlink. You can use it to create Java runtime images that contain just the Java modules you need for your application (reducing deployment size) or you can create a runtime image that includes your app (giving you a single deployment unit that doesn't require a JRE/JDK to be installed).
So, as I understand this moving toward modular system can be done in steps, so at the beginning all of the code is in "unnamed" module/modules and it's possible to gradually introduce this safety-belt that molecularity give us without breaking up the existing solution?
What I mean is, if any migration of this size (i.e. whole application) of existing codebase to modular Java application is going to happen, it needs to be done incrementally as no other option is feasible in my opinion. Hence wanted to confirm it's doable.
posted 11 months ago
You are correct. Once you've migrated your Java 8 application to the Java 9+ class path, it runs in the so-called unnamed module whereas all JDK code runs in proper explicit named modules.
Starting form there, several modularization strategies exist:
Top down: You can start with the JAR that contains the application's entry point and turn it into a modular JAR by adding a module-info.java to its source tree. You will then compile and run it from the module path, which forces you to pull its dependencies on the module path as well. If these dependencies are modular JARs, too, their dependencies need to be on the module path as well and so forth. Non-modular JARs that end up on the module path will be so-called automatic modules - their special power is that they can access the unnamed module (explicit modules can't do that) and so their dependencies can stay on the class path. The effect of all this is that, at run time, the top of your dependency tree is an explicit module, some of its dependencies may be as well, but then comes a buffer of automatic modules with most of the other dependencies on the class path. You can then incrementally modularize modules from the top down by adding module declarations and pulling their dependencies onto the module path.
Bottom up: Look at a JAR at the bottom of your dependency tree, ideally one with no dependencies outside the JDK and add a module-info.java to its source tree, compile and run it from the module path. The interesting bit is that JARs further up the tree, which are still on the class path, can access it, because they are in the unnamed module, which reads all other modules. You then work your way up the tree.
Inside out: Putting these strategies together you could actually start anywhere in your dependency tree and move up- and downwards from there. Heck, you could even throw darts at the tree and modularize every JAR you hit, but there's no point to that.
Note that these strategies are more complicated than moving to the module path in one fell swoop. If you can take a modularization day/week and have a developer, a small group, or maybe the entire team do nothing but creating modules so your entire code base gets modularized at once, you will be in a cleaner state. That said, if your dependencies are not fully modularized you're effectively in a top-down scenario where your part of the tree is modules on the module path and you're waiting for your dependencies to catch up.