Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Modular Programming in Java 9
Modular Programming in Java 9

Modular Programming in Java 9: Build large scale applications using Java modularity and Project Jigsaw

eBook
R$80 R$173.99
Paperback
R$217.99
Subscription
Free Trial
Renews at R$50p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Modular Programming in Java 9

Introducing Java 9 Modularity

This book covers modularity features in Java 9--an important new change to the Java programming language. We'll look at its impact on Java development and how you can use it to build powerful modular applications. The Java 9 release also comes with a few other changes, such as support for HTTP 2.0 and a shell called jshell that lets you run Java code snippets in a Read-Eval-Print-Loop (REPL). While these are exciting new changes, they are not the focus of this book. We will be primarily focusing on the modularity features, which are arguably the most important and powerful among all the new changes with the Java 9 release.

This chapter provides an introduction to the new module features in Java 9 by covering the following topics:

  • Examining two important structural and organizational problems when building Java applications today, and their implications
  • Why does Java even need modularity features? What are we missing right now? And what do we gain from modularity?
  • Introducing the Java Platform Module System (JPMS)
  • Understanding the benefits that the Java modular system aims to provide

Modularity in Java

If you've been a developer for any length of time, you'll have very likely realized that the word module is perhaps one of the most overused terms in software development. A module can mean anything ranging from a group of code entities, components, or UI types, to framework elements to complete reusable libraries. Sometimes, we use the word to imply multiple meanings in the same context!

There is a good reason for that. When writing code, we typically try to break the code base down into smaller units in order to manage complexity. For anything more than very simple programs, having a monolithic code base is not a good idea. That's why modular programming is a generally favored software design approach. There are two important goals that modularity in software development usually achieves, which are as follows:

  • Divide and conquer approach

What do you do when you need to solve a large and seemingly insurmountable problem? You break it down! You'll very likely split it into smaller problems and solve them individually.

The principles of modularity encourages separating large code bases into smaller encapsulated units of functionality that are then composed to work together as a bigger unit. This aligns well with the approach we humans usually take to solve large problems. Also, once you've got a bunch of smaller modules with specialized concerns, you can use those to solve various other problems. Thus, we also achieve reusability!

  • Achieving encapsulation and well-defined interfaces

When you build modules, you have the ability to hide the internal implementation from the consumers of your module. The hidden implementation details are usually referred to as being encapsulated, and what you expose to the consumers of your module is usually called the interface of your module.

Although Java developers have leveraged many different patterns and best practices over the years in order to write and structure modular and maintainable code, the language has never had native support to create modular units and build modular applications, until Java 9. With Java 9, Java developers now have the ability to create smaller units of code with a new construct called Java modules that they can group together like building blocks in order to compose larger applications. In addition to introducing this feature to the language, Java 9 also comes with what is probably the biggest overhaul to the core Java code base itself. The Java Runtime Environment (JRE) and the Java Development Kit (JDK) have been rewritten to use the concepts of modularity so that the core Java Platform itself is modularized.

When learning about Java 9 module features, it's important to understand what those new features add to the language when compared to the other features the language already has. Can't we write well organized code in Java 8? In fact, one of the benefits of object-oriented programming is indeed the idea of breaking down functionality into sub-units called objects or classes. We've been writing code like this in Java since version 1. Every Java class contains a portion of the overall application functionality that happens to belongs together. We have the ability to encapsulate some functionalities as internal to a class (as private) and some others as external (or public).

And then there's something in between with protected, thanks to the concept of packages.

Rethinking Java development with packages

Think about why we use packages in Java. We could very well write entire Java applications without creating any packages and, thereby, using just the default unnamed package. It would work! However, unless it's a simple or throwaway application, that's not a good idea. The idea of packages is to group your Java types into namespaces that signify the relationship, or perhaps a common theme among those types. It makes code easier to read, understand, and navigate.

The following diagram shows an example of classes organized in packages. Adding all classes to a single package (left) is not good practice. We typically group related classes into well-named packages that describe the nature of the classes in them (right):

There's really no rule about what types belong together in a package. However, it's generally understood that when you create a package and put a bunch of Java types in it, the types are usually related in some way. You could very well write any random set of types in the same package and the compiler wouldn't care. However, anyone else who ends up working on your code could potentially hate you forever, so this is not a wise thing to do! Having related types in common packages also has the benefit of those types being able to access the protected members of each other. This is another level of encapsulation--any protected members or methods are encapsulated within types of a package. (Although, there's an exception to this, as inherited classes are able to access private members across packages.)

So, if the idea of modular programming is to break code and functionality into encapsulated units, there's a sense in which you can do some kind of modular programming in Java well before Java 9.

The following table shows the various ways in which you can encapsulate code in Java before Java 9:

What to encapsulate

How to encapsulate

Encapsulation boundary

Member variables and methods

private modifier

Class

Member variables and methods

protected modifier

Package

Member variables, methods, and types

No modifier

(default package - protected)

Package

 

Isn't that good enough? Well, not really. The preceding table is where a limitation in the modular ability of the language becomes apparent. Notice the What to encapsulate column. Most of the encapsulation features provided by these modifiers focus on controlling access to member variables and methods. The only way you can really protect access to a type is by making it package-protected. That, unfortunately, ends up making access difficult for even your own library code to access the type, and you are forced to move all the code that accesses that type into the same package. What if you want more?

Why, you ask? There are a couple of problems with approaching modularity with just the preceding paradigm available in Java 8 and earlier. Let me explain both those problems with two stories.

The unfortunate tale of a library developer

Meet Jack. He's a Java developer at a medium-sized enterprise organization. He's a part of a team that writes code to do data processing. One day, Jack wrote some Java code to sort a list of usernames in alphabetical order. His code worked well without any errors and Jack was proud of his work. Since this was something that could be used by other developers in the organization, he decided to build it as a reusable library and share it with his colleagues as a packaged JAR file. Here's the structure of Jack's library:

His code belonged to two packages--acme.util.stringsorter and acme.util.stringsorter.internal. The main utility class was StringSorterUtil with one method--sortStrings. The method in turn internally called and delegated the sorting responsibility to the BubbleSortUtil.sortStrings() class  from a class in the acme.util.stringsorter.internal package. The BubbleSortUtil class used the popular Bubble Sort algorithm to sort a given list of Strings.

All that any developer had to do was to drop the jar in the classpath and call the StringSorterUtil.sortStrings() method by passing in an list of strings they needed sorting. And they did! Jack's little library became a hit! His colleagues loved the convenience that his library provided and they started using it to sort many things, such as names, tokens, addresses, and so on.

A few months later, Jack happened to talk to Daryl at the water cooler, and as usual, their conversation veered towards a discussion about their current favorite sorting algorithms. Daryl couldn't stop talking about his new-found love for hash sort. He said he found it performs much better than bubble sort, and it was unabashedly his new favorite algorithm! Jack was intrigued. He went to his desk and ran a few tests. Daryl was right! Hash sort outperformed bubble sort in most of his tests. Jack knew right then that he had to update his sorting utility to use hash sort. He added a new class, HashSortUtil in the acme.util.stringsorter.internal package and removed BubbleSortUtil.

The following is the structure of Jack's library after the change:

Thankfully, he had a separate internal class that did the sorting, so the process to invoke the StringSorterUtil.sortStrings() utility wouldn't change. Everyone could just drop in the newer version of the JAR and everything would work just fine.

But it didn't! A few of the code builds in his company started failing. It turned out the culprit was the newer version of Jack's library. Jack couldn't believe it. He didn't miss anything, did he? Well, no. All the projects that used just the StringSorterUtil class worked just fine. However, it turned out that some of the developers ended up using the BubbleSortUtil class in the internal package directly. It was available in the classpath, so they had just imported and used it. Now, since that class didn't exist in the new jar anymore, their code couldn't compile!

Jack sent out an email instructing everyone using BubbleSortUtil to update their code to use StringSorterUtil instead. However, it turned out the BubbleSortUtil class was being used in multiple places by that time, and it wasn't an easy task to change them all. "Couldn't Jack just put the BubbleSortUtil class back?" they asked. Jack yielded to their requests and the next version of the library had both the SortUtil classes (and would possibly do so well into the foreseeable future), even though it internally used only one of those two classes.

After the dust settled, Jack sat at his desk and wondered what had gone wrong. What could he have done to prevent this problem? Clearly, naming the package as internal did not prevent developers from using it. One solution would have been to write that internal bubble sort type as package-protected and move the external type to the same package. This way, he could leverage the third mechanism in the preceding encapsulation table. However, he liked the idea of separating the bubble sort class into its own type and package. Also, imagine if this were a bigger library and there was a common shared class that was supposed to be internal. In that case, pretty much all types in that library that need the internal type have to exist in the same package as that internal type! Wasn't there a better way to encapsulate the internal types?

The impossible task of a deployment engineer

Meet Amit, a deployment engineer at yet another enterprise technology firm. His job is to make sure that during every product release, the organization's code base is compiled and deployed properly in the production environment. During every release, he pulls in the application code and all the necessary jar files and places them in the classpath. He then starts the application that results in the Java Virtual Machine (JVM) loading all the classes and initializing execution.

One night, there was a major product feature release. There were a lot of changes to the code that were all supposed to be deployed and launched together. Amit made sure that all the new code was compiled properly and he had all the necessary jars in the classpath. He then had to start the application. Before he clicked on the button to launch the build, Amit wondered if there was some way he could make sure everything was good and that the application would work without any runtime class errors.

One thing that could potentially go wrong was if he had missed adding a certain class or jar in the classpath. Was there a way he could statically verify whether all the classes were available without actually running the application?

Each JAR bundled a set of types in a set of packages. Each type therein could potentially import other types, either from the same JAR or from other jars. To make sure he has all the classes in the classpath, he has to go to each class and verify that all its imports are in the classpath. Considering that the number of classes in his application run to thousands, it's a Herculean task.

The following diagram is a simplified version of what a sample deployed Java application looks like:

There are four jar files in the picture above, each of which contains packages and classes within them. Jar 1 is deployed in Classpath A, Jar 2 and Jar 3 in Classpath B, and Jar 4 in Classpath C. Let's assume each jar has two classes as indicated by the smaller white boxes. The three paths are configured as classpaths for the Java runtime, so the runtime knows to look at all three paths to scan and pick up classes.

After scanning all the classpaths, this is what the structure looks like to the Java runtime:

Notice that the runtime doesn't care which directory or classpath the package/type is in. It also doesn't care which jar the package/type is bundled in. As far as the Java runtime is concerned, it's just a flattened list of types in packages!

In Java, a classpath is a just set of paths. Any of those locations could have the jars and classes that the application needs to work. You can immediately see how easy it is for things to break! There's always a possibility that some of the classes that the application uses are not available in the classpath. Perhaps a missing jar or library. If the runtime doesn't have a specific class it needs, the application could start running fine, but throw a NoClassDefFoundError much later. That too, only when the execution hits a point where a missing class is actually needed.

This is a huge and very real problem in large Java applications today. There is a whole ecosystem of solutions that have sprung up to address this. For example, tools and build utilities, such as Maven or Gradle, standardize the process of specifying and acquiring external dependencies. Process-based solutions such as continuous integration aim to solve the unpredictable nature of builds across various development environments. However, all that such tools can do is make the process predictable. They cannot verify the validity or accuracy of the result that they help assemble. Once the dependencies are fetched, there's nothing that those tools can do to detect missing or duplicate types in the classpath.

Back to Amit's story. Having no way to verify whether all the classes are available up front, Amit hopes for the best and deploys the application. The application starts up fine and runs for a couple of hours without any errors. However, there's still no saying if he's got it right. Maybe there's a class in there that hasn't been executed yet, but when it has, the JVM might realize that it cannot find one of its imports. Or, maybe, there are duplicate versions of the same class in the classpath and the JVM picks up the first copy it finds. Wasn't there a better way to ensure that any given Java application will work reliably in advance?

The classpath problem

We've seen two problems in Jack's and Amit's stories. Jack needed an effective way to encapsulate portions of his library, but couldn't. Amit needed a way to ensure reliable execution of his application without actually executing it. Both Jack and Amit didn't really have a solution to their problems because of the way classpath resolution works in Java. We may sometimes mistakenly think of a JAR file as a way to build a reusable module in Java, but that's unfortunately not the case. A JAR file is just a convenient bundle of classes. Nothing more! Once in the classpath, the JVM treats classes in a JAR no differently from separate class files all in the same root directory. At runtime, as far as the JVM is concerned, an application is just a set of classes in a flat list of packages.

What's worse is, once a class is in the classpath, it's free for all. It's incredibly easy for any developer to use a type they are not supposed to, or a type that might be available for them during compile time, but not at deployment/runtime. Or there could be multiple copies or even multiple versions of the same class in two different classpath locations, making it unpredictable which version the runtime will actually pick up during execution. There's a problem commonly called JAR hell, which refers to several issues resulting from mismatched and incorrect classes and versions in JAR files.

This problem is exacerbated in huge code bases with hundreds of thousands of classes. Imagine all those classes in your application as a flat list with no structure! It's a nightmare to maintain and organize. The bigger the code base, the bigger the problem. To illustrate this, let's take the classic example of a code base that's written in Java, that's incredibly large and complex, and has lasted for many years now. It is perhaps one of the oldest Java code bases ever, and still it continues to grow and change at a fairly rapid pace. Any guesses? Well, it's the Java platform itself!

Java - the 20-year-old code base

Talk about a monolith! Java has come a long way since its first release in 1996. The first major release of the JDK had a little over 500 public classes. A far cry indeed from JDK 8 released in 2014, which counts upwards of 4,200 public classes and over 20,000 total files.

The following commands extract the rt.jar file, a library JAR file bundled in JDK 8, and count the number of classes in it. With the Java 8 version I have installed on my machine, the count is 20651:

The JDK and the runtime, the JRE, have continued to grow over the years. There are a lot of features that have been added to the language, so this growth is understandable. However, the Java language is also notorious for going to great lengths to maintain backward compatibility and for its reluctance to deprecate features unless it is absolutely necessary. So, in a way, the current size of the runtime is a little over what it could have ideally been.

Normally, most application developers wouldn't need to worry about the JDK code base. They just focus on their application code. However, the contents of the runtime does matter for application execution because of the way it is bundled. Traditionally, every JRE has had all the classes necessary for runtime bundled into a single JAR that resides in the lib directory called rt.jar. The name rt, as you might have guessed, stands for runtime.

Not only is this huge monolith of classes unnecessarily bulky in size, it also adds performance overheads for the Java Virtual Machine to manage. And that's a price the execution environment of all your applications have to pay, irrespective of whether all of those classes are being used or not.

Legacy classes

A good example of classes that you don't need is the set of classes in the JRE related to CORBA. Ever heard of CORBA? If you haven't, don't despair. It's for a reason! It's an old technology that was introduced to the Java runtime back in version 1.4. It has mostly fallen out of popular use since then. Considering most applications don't use the CORBA technology anymore, wouldn't it be great if apps could be bundled with JREs that do not contain the unnecessary CORBA classes?

That's unfortunately not possible, again, because of rt.jar. Since everything gets bundled into a single runtime JAR, you cannot pick and choose what features you need. Everybody gets everything. And since the runtime has been increasing in size, so has the standalone deployable application. This is a more significant challenge when the runtime needs to be used on smaller devices with limited resources. If you are bundling the runtime with a simple Hello World application that uses just a handful of classes from the runtime, you have no option but to bundle a whole lot of unused classes in rt.jar with it. And, yes, even those old CORBA classes join in for the ride!

Java 8 introduced the concept of profiles, and with that, you can technically deploy smaller runtimes. But they do have some drawbacks. Also, this feature was just an initial step in the introduction of modularity features in Java 9 anyway. We'll examine compact profiles in detail in Chapter 4, Introducing the Modular JDK.

Internal APIs

Remember the problem that Jack had with his BubbleSortUtil class? It was a Java class he wrote with the intention of it being private to his library. However, even though it started out as a private internal class, it ended up being a public class because other developers just decided to use it.

That was just a small library. Now, think about a library as big and as widely used as the Java runtime. The Java runtime obviously bundles in internal classes that are required for its functioning and aren't meant to be used by application developers. However, considering the magnitude of its usage, it isn't surprising that some of the internal classes are inadvertently used by developers anyway.

A classic example of this is a class called Unsafe in the sun.misc package. This ominous sounding class has been a part of every major JDK release for a while now. Can you guess what it does? It contains a collection of methods that perform, according to the author of the class, low-level unsafe operations. Yes, it actually says that in the comments in the class! For instance, it has a method that gets a value from a memory address. Not a typical day's work for a Java application developer! You wouldn't, and ideally shouldn't, do something like that as an application developer. This is why the class has been marked as an internal API. Want to look up its Javadoc to use it? You won't find it in there. Want to create a new instance of the class? Its constructors are marked as private. If you do somehow use it and compile your code, every Java compiler since Java 6 will give you a nasty warning, discouraging the usage of the class. And, if you still need more reasons to avoid using it, you'd be best served to just look at the name of the class!

You must have guessed what's coming by now. The sun.misc.Unsafe class has now been used in multiple projects by many developers to perform those very low-level operations, in spite of all those preventive measures that the Java runtime authors have put in place. One could argue that it implements functionality that isn't commonly available elsewhere, and for a developer who needs to do something like that, nothing beats just picking it up while it's available in the classpath and ready to use. Unsafe isn't the only internal API that is being used this way, of course. There are a few more internal classes, many in the sun.* packages, that developers have used over the years even though they shouldn't. Moreover, as long as developers continue to use these APIs, it becomes harder to remove them from the runtime. This has ended up continuing the existence of these classes in subsequent versions of the runtime, thereby allowing more developers to use them!

These limitations of the Java runtime and library system have been felt for a while now. All the problems I've outlined so far exist because of the lack of ability to create modular units of code in Java. Such a construct simply hasn't existed in the language so far. The need for it has been strongly felt in the community.

Multiple proposals for a module system for Java have been made over the years, including JSR-277 way back in 2005 (https://jcp.org/en/jsr/detail?id=277) and JSR-294 (https://jcp.org/en/jsr/detail?id=294) in 2006. After facing several hurdles, modularity is finally coming to Java with the 2017 release of Java 9 with JSR-376 (https://jcp.org/en/jsr/detail?id=376), the spec titled Java Platform Module System, as well as Project Jigsaw.

Acronym alert: JCP and JSR

JCP: The Java language specification has, for a long time, been a community-owned asset. There is no one central authority that has complete control and the decision-making power in how the language evolves. Each of us, as Java developers, can have a say in how we want the language to change and grow. The Java Community Process (JCP) is a mechanism, introduced in 1998, that allows anyone interested in the future of the language specification to register, provide input, and take part in the technical specifications process. Go to https://jcp.org to learn more.

JSR: Let's say you are a part of the Java Community Process, and you have a great idea for a change in the language specification. What you do is create a Java Specification Request (JSR)--a formal document that describes the proposed changes. JSRs are reviewed and voted upon as a part of the community process before they become final. Once a JSR does become final, it is worked on and eventually becomes a part of the language specification.

Fun fact: The Java Community Process itself is an important part of the language, and so changes to it are also handled just like any other changes to the language--by submitting a Java Specification Request for it. Yes, there's the JSR that describes the JCP!

Java Platform Module System

The modularity features in Java 9 are together referred to by the name Java Platform Module System (JPMS). It introduces a new language construct to create reusable components called modules. The Java Platform Module System makes it easy for developers to create contained units or components that have clearly established dependencies on other modules. With Java 9 modules, you can group certain types and packages into a module and provide it with the following information:

  • Its name: This is a unique name for the module
  • Its inputs: What does the module need and use? What's required for the given module to be compiled and run?
  • Its outputs: What does this module output or export out to other modules?

I'll explain the input and output configuration shortly, but at a very high level, these three pieces of information are what you typically supply when you create a new module. Whenever developers need to create any components that are meant to be reusable, they can create new Java modules and provide this information to create a unit of code with a clear interface. Since a module can contain both its inputs and outputs specified formally, it adds a whole set of advantages compared to the classpath approach that we've critiqued so far.

Let's now look at the process of creating a module step by step. We'll look at it at a conceptual level now, and we'll cover the syntax in Chapter 2, Creating Your First Java Module. Let's say you want to create a reusable library and you've decided to put your code in a Java 9 module. Here are the steps you need to follow:

  1. Create a module and give it a name: Every module has a name associated with it, for the obvious purpose of referring to it. You can give a module any name that you'd traditionally give to types. All the rules you are already familiar with regarding Java package names apply here (so certain characters like '/' or '-' aren't allowed, but '_' or '.' are okay). The recommended way to name a module is to use the reverse domain name convention, similar to the way you name your packages. So, for example, if someone in Acme Corp wrote an analytics module, they'd probably name the module com.acme.analytics.
  2. Define the module inputs: Not many modules can realistically be self-sufficient. You'll often need to import types that aren't in your module. This is where the module input configuration comes into play. When you create a module, you explicitly need to declare which other modules you need for your code to work. You do that specifying which modules your module requires.
  3. Define the module outputs: We've seen that in a traditional JAR file system, placing Java types in a JAR file doesn't really mean anything and every public type is accessible to every other type in the classpath, irrespective of which JAR it is in. A module behaves differently. By default, every Java type you place in a module is accessible only to other types in the same module. Even if the type is marked public! In order to expose types outside the module, you need to explicitly specify which packages you want to export. From any module, you can only export packages that are in that module. Once you've exported a package, all types in that package are potentially accessible outside the module. This enables every Java module to clearly separate and hide internal packages that are to be used only inside the module and expose only types that are intended to be used externally. If a Java type is in a package that isn't exported, then no other type outside the module can import it, even if the type is public!

Note the difference between the things you export from a module (which are packages) and the things you import or require (which are other modules). Since we are exporting types from a module at a package level, why not require packages too? The reason is simple. When a module requires another module, it automatically gets access to all the packages that that module exports. This way, you don't have to specify every package that your module needs. Just the name of the module you depend on will suffice. We'll look at the access mechanisms in much more detail in Chapter 3, Handling Inter-Module Dependencies.

The following diagram illustrates the input and output definitions of a typical module:

JPMS was designed with two primary goals in mind:

  • Strong encapsulation: We've seen the dangers of having every public class accessible to every other class in the classpath. Since every module declares which packages are public and isolates those which are internal, the Java compiler and runtime can now enforce these rules to make sure that none of the internal classes are being used outside the module.
  • Reliable configuration: Since every module declares what it needs, the runtime can check whether every module has what it needs well before the application is up and running. No more wishing and hoping that all the required classes are available in the classpath.

You can guess how happy Jack and Amit would be to hear this! Thanks to strong encapsulation, Jack would just need to put all of his StringSorter code in a module and export just his public package. Thus, his internal package would be hidden and not accessible by default. And, thanks to reliable configuration, Amit can always confidently say whether a given set of modules have all their dependencies met before running the application.

In addition to these two core goals, there has been another important goal that the module system was designed for--to be scalable and easy to use even on huge monolithic libraries. As a validation of that, the Java 9 team went ahead and modularized what's pretty much the oldest and biggest Java code base they could get their hands on--the Java Platform itself. This task, something that ended up involving significant effort, was performed under the name Project Jigsaw.

Project Jigsaw

Alan Bateman, a member of the Java Platform Group at Oracle said this is in his talk in Java One in September 2016:

Modular development starts with a modular platform.

No matter what the application is about, there's one set of libraries that every Java program is guaranteed to use without a doubt--the Java Platform. For Java developers to be writing modular Java code, it's essential for the core Java platform and the JDK library to be modular as well. Before Java 9, all the classes and types in the JDK had such complicated inter-dependencies that they resembled a big bowl of spaghetti.

Not only is the final rt.jar bundle unnecessarily large, it makes the JDK code base itself harder to change and evolve. Considering how any type in such a huge code base could be used by any of the other thousands of types in the platform, I wouldn't want to go in there and make any major changes to that code. Another problem with the platform is that it has always lacked ways to hide and encapsulate internal platform APIs such as sun.misc.Unsafe. The platform itself could very well use the same strong encapsulation and reliable configuration benefits that JPMS gives us.

With Java 9, we've finally got a modular JDK to build on top of. Various different sets of related JDK classes are bundled into separate modules, each with its own imports and exports. For example, SQL related types are in a module called java.sql. XML functionality has gone into the java.xml module, and so on. We'll be looking at these out-of-the-box modules in more detail in Chapter 3, Handling Inter-Module Dependencies.

The following is an illustration of a subset of the new Java 9 platform modules. Don't worry about the individual names. We'll cover platform modules in detail in Chapter 4, Introducing the Modular JDK:

Project Jigsaw claims the following as its primary goals. It's important to keep this in mind as you learn about the impact of the modularization of the platform:

  • Scalable platform: Moving away from a monolithic runtime and enabling the ability to scale the platform down to smaller computing devices.
  • Security and maintainability: Better organization of the platform code to make it more maintainable. Hiding internal APIs and better modular interfaces to improve platform security.
  • Improved application performance: Smaller platform with only the necessary runtimes, resulting in faster performance.
  • Easier developer experience: The combination of the module system and the modular platform to make it easier for developers to create applications and libraries.

What does this mean for application developers? The most immediate difference is that not all types in the JDK are now accessible in your code. The same mechanisms we saw apply to our modules work with the Java modules too. Any time you depend on a platform class, you'll have to import into your module the right platform module that contains that class. And, even then, you'll be able to use the class only if it has been exported from the module and is public.

This way, the JDK code base also gets all the advantages of the strong encapsulation and reliable configuration that the JPMS promises. There are potential backward compatibility issues though. What if you used a JDK class in JDK 8 or earlier that's now an encapsulated class in a module? That code wouldn't work in Java 9! The platform uses the encapsulation features to protect certain internal JDK classes from external use. So, any code that depends on such classes in Java 8 or earlier cannot be migrated to Java 9 without removing that dependency first. There are a few challenges associated with moving code from Java 8 or earlier to Java 9. We'll look at Java 9 migration-related challenges and best practices in Chapter 9Module Design Patterns and Strategies.

Another important aspect of modularity that most modular platforms have to deal with, and we haven't covered so far, is versioning. Are modules versionable? Can you declare dependencies between modules that specify which versions of the modules need to work together? You cannot! Java Platform Module System does not support versioning today. We'll briefly examine the reasons why in Chapter 3, Handling Inter-Module Dependencies.

Summary

In this chapter, we looked, at a high level, at some limitations of the traditional way of building reusable components in Java using JAR files. We saw how packaging libraries in JAR files doesn't allow developers to encapsulate inner APIs and types. There's also no way to reliably figure out whether a given application has all the necessary classes in the classpath. We learned how these problems that developers face in their code are not only present in the JDK code base itself, but are actually an issue on a much bigger scale. We understood the Java Platform Module System and the two primary goals that it set to achieve--strong encapsulation and reliable configuration. We learned about Project Jigsaw and the effort to modularize the core JDK using the same modular paradigm that's available to developers to use in their code.

At this time, you are probably wondering how the concept of modularity manifests in the Java language. What does a Java module look like?

In the next chapter, we'll answer these questions by creating our first Java 9 module, and get started on our sample application project which we'll be working on throughout this book.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Master design patterns and best practices to build truly modular applications in Java 9
  • Upgrade your old Java code to Java 9 with ease
  • Build and run a smooth functioning multi-module application.

Description

The Java 9 module system is an important addition to the language that affects the way we design, write, and organize code and libraries in Java. It provides a new way to achieve maintainable code by the encapsulation of Java types, as well as a way to write better libraries that have clear interfaces. Effectively using the module system requires an understanding of how modules work and what the best practices of creating modules are. This book will give you step-by-step instructions to create new modules as well as migrate code from earlier versions of Java to the Java 9 module system. You'll be working on a fully modular sample application and add features to it as you learn about Java modules. You'll learn how to create module definitions, setup inter-module dependencies, and use the built-in modules from the modular JDK. You will also learn about module resolution and how to use jlink to generate custom runtime images. We will end our journey by taking a look at the road ahead. You will learn some powerful best practices that will help you as you start building modular applications. You will also learn how to upgrade an existing Java 8 codebase to Java 9, handle issues with libraries, and how to test Java 9 applications.

Who is this book for?

This book is written for Java developers who are interested in learning and understanding the techniques and best practices to build modular applications in Java. The book assumes some previous programming experience in Java 8 or earlier, familiarity with the basic Java types such as classes and interfaces, as well as experience in compiling and executing Java programs.

What you will learn

  • • Get introduced to the concept of modules and modular programming by working on a fully modular Java application
  • • Build and configure your own Java 9 modules
  • • Work with multiple modules and establish inter-module dependencies
  • • Understand and use the principles of encapsulation, readability, and accessibility
  • • Use jlink to generate fully loaded custom runtime images like a pro
  • • Discover the best practices to help you write awesome modules that are a joy to use and maintain
  • • Upgrade your old Java code to use the new Java 9 module system
Estimated delivery fee Deliver to Brazil

Standard delivery 10 - 13 business days

R$63.95

Premium delivery 3 - 6 business days

R$203.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Aug 29, 2017
Length: 298 pages
Edition : 1st
Language : English
ISBN-13 : 9781787126909
Vendor :
Oracle
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Brazil

Standard delivery 10 - 13 business days

R$63.95

Premium delivery 3 - 6 business days

R$203.95
(Includes tracking information)

Product Details

Publication date : Aug 29, 2017
Length: 298 pages
Edition : 1st
Language : English
ISBN-13 : 9781787126909
Vendor :
Oracle
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
R$50 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
R$500 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just R$25 each
Feature tick icon Exclusive print discounts
R$800 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just R$25 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total R$ 736.97
Design Patterns and Best Practices in Java
R$272.99
Modular Programming in Java 9
R$217.99
Java 9 Data Structures and Algorithms
R$245.99
Total R$ 736.97 Stars icon
Banner background image

Table of Contents

12 Chapters
Introducing Java 9 Modularity Chevron down icon Chevron up icon
Creating Your First Java Module Chevron down icon Chevron up icon
Handling Inter-Module Dependencies Chevron down icon Chevron up icon
Introducing the Modular JDK Chevron down icon Chevron up icon
Using Platform APIs Chevron down icon Chevron up icon
Module Resolution, Readability, and Accessibility Chevron down icon Chevron up icon
Introducing Services Chevron down icon Chevron up icon
Understanding Linking and Using jlink Chevron down icon Chevron up icon
Module Design Patterns and Strategies Chevron down icon Chevron up icon
Preparing Your Code for Java 9 Chevron down icon Chevron up icon
Migrating Your Code to Java 9 Chevron down icon Chevron up icon
Using Build Tools and Testing Java Modules Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.5
(2 Ratings)
5 star 50%
4 star 50%
3 star 0%
2 star 0%
1 star 0%
Java_Guy Sep 27, 2017
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This is one of the best book I came across recently. Author had really explained the topics well so as to understand the core concepts of Modular Programming in Java 9. I will certainly recommend this book to readers !!
Amazon Verified review Amazon
Mozart Brocchini Sep 07, 2017
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
Disclaimer: I was a technical reviewer of this book.The author gently introduces all concepts and then applies them with simple code examples or executing new commands on the terminal that were specifically added to Java 9 to help with modularity features.You will start by learning what problems the modularity features solve, then learn how to create your first module and progress incrementally all the way up to migrating existing code to java 9 and ultimately using modules with build tools and testing modules. You will also learn how the Java platform itself has been modularized and what benefits that brings. There is a new game changer feature that you shouldn't miss, the linking development phase which happens between compiling and executing code. Linking allows you to create self contained lightweight runtime images for your application with the usage of jlink tool rather then having to deploy the entire rt.jar like we did with previous versions of Java.I started reading this book with a lot of skepticism, my initial thinking was "Does modularity add any value to software development in today's world where modern architectures just expose APIs backed by microservice back ends ?". Well, it turns out that some of the new modularity features added to Java 9 like linking, actually help with creating more lightweight services.Fortunately, it turns out that this book will help Java 9 programmers with all the tasks related to modularity, including module design, best practices and patterns for modularizing new applications as well as retrofitting existing monoliths into modular systems which could later be broken into standalone microservices.I'm giving a four star rating based on topic coverage and accuracy, this book is excellent because it has everything you need to know about modularity with Java 9, you will find articles on web containing certain concepts but likely all articles will be incomplete and you will be only getting part of what Java 9 modules are about. While it is tempting to jump into learning the modularization features based on short tutorials, the modularity features are game changers and may only disappoint you if you start with a high level of frustration when failing to get things things done because of lack of knowledge. Just to give you and idea on how Java 9 is different, in Java 9 modular development, the classpath is no longer used to find dependencies.I obviously have not read all Java 9 books and never will, but my guess is that even Java 9 books that are not specifically targeting modularity will likely be short in modularity content.What could be improved:A few examples are based on older architectures and practices, those examples were chosen to exemplify some problems that modularity solve, but those issues no longer exist in more modern applications using microservices architecture and DevOps automation practices.Also, sometimes the topics feel a bit long for an experienced architect like me who wants to go right to the point.The verdict:If you are willing to learn Java modularity the right way, or have a complete reference focused exclusively on the new modularity features added in Java 9, this book is for you.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact [email protected] with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at [email protected] using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on [email protected] with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on [email protected] within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on [email protected] who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on [email protected] within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela