Pattern 3 - Optional dependencies

We've seen how Java did not have an option for reliable configuration up until Java 9. You could add or remove certain classes and JARs from the classpath before running and the application would still execute (or at least, starts executing)! There are some utility libraries and frameworks in Java that have made good use of this flexibility.

Consider the Spring Framework. Spring is a popular application framework that uses and orchestrates functionality across a lot of other dependent libraries and frameworks by scanning the classpath for available libraries that it can work with. If you'd like Spring to use some of these supported libraries, just dropping certain necessary jars into the classpath is enough for Spring to pick it up and use its functionality. And if you don't, the Spring framework can still function without them, albeit without the optional functionality.

This flexibility plays an important role in the ease of use of these frameworks. Now, with Java 9 and strict requirements for module dependencies, wouldn't we be losing this flexibility? There's no optionally dropping jars into the classpath anymore! Things are much more strict and controlled now. Every module that a given module needs should be explicitly specified with a requires clause in the module definition. Given this new state of affairs, how could you build such modules that are optional and with drop-in flexibility?

The answer is optional dependencies. In Java 9, you can specify a given module dependency as optional by using the requires static qualifier. The syntax is:

    module <module-name> { 
      ... 
      requires static <optional-module-dependency>; 
    } 

The static qualifier tells the module system that the module required is optional. The module should still be available at compile time (because javac needs to compile the code and references after all!). But it is optional at runtime. If the module isn't available during runtime, java won't complain about the module's unavailability like it would with the requires only clause. It proceeds with execution assuming you know what you are doing. This new feature enables you to have modules with a bunch of require static optional dependencies, which can be freely dropped into the module path.

Here's how it works:

  • When you have a module that optionally depends on one or more modules, use the requires static clause to establish optional dependency in the module definition. If module A optionally requires module B, you specify requires static B in module A's definition.
  • During development and compile time, you don't have to do anything different. You could use the exported types from the optional dependencies just like a regular requires dependency. As always, the module(s) with the optional dependency needs to be available at compile time for the code to compile.
  • At runtime however, things are different. This time, you can execute your application irrespective of whether the module with the optional dependency is available or not. If the module is available, it gets picked up fine. But if it isn't, you get a NoClassDefFound error. While it's not mandatory, it's a good idea to write code to handle this error scenario, in case the module you optionally require isn't available.
..................Content has been hidden....................

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