Spring's need for optional dependencies

Peter Levart peter.levart at gmail.com
Sat Dec 19 13:08:01 UTC 2015

Hi Paul,

On 12/18/2015 05:49 PM, Paul Benedict wrote:
> Peter, when you say Jigsaw  "doesn't search for module B" when it's 
> optional, what do you mean by "search"?

To construct a layer (java.lang.reflect.Layer), a configuration 
(java.lang.module.Configuration) must 1st be created (from example in 
the javadoc):

  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
  *     Configuration cf
  *         = Configuration.resolve(finder,
  *                                 Layer.boot().configuration(),
  *                                 ModuleFinder.empty(),
  *                                 "myapp")
  *                        .bind();

...which takes a ModuleFinder, a parent Layer's configuration, and a set 
of root module names ("myapp" in above example). The resolve() method 
uses module finder and root module names to "search" for root modules 
and all their transitive dependencies (mentioned in their "requires" 
clauses). If any of those modules is not found, exception is thrown. The 
transitive closure of modules is then augmented with providers 
("provides" clause) of services that those modules "use" (the bind() 
method). This is how the final set of modules that are part of the layer 
that is build from the configuration is constructed. Other modules that 
are left behind in the -modulepath directories and are not part of the 
configuration are not available to the runtime.

I'm suggesting that "requires optional" semantic should not count as a 
"soft" dependency when the transitive closure of modules is computed, 
but should add a read edge if the target module is included in the 
configuration by some other means (a normal "requires" from the module 
already part of configuration, -addmods option, etc.).

Regards, Peter

> Cheers,
> Paul
> On Fri, Dec 18, 2015 at 10:42 AM, Peter Levart <peter.levart at gmail.com 
> <mailto:peter.levart at gmail.com>> wrote:
>     Hi Paul,
>     On 12/18/2015 05:14 PM, Paul Benedict wrote:
>>     Adding read edges at runtime is not a backward compatible
>>     solution. Jigsaw should automatically allow you to read anything
>>     your Module Descriptor gives you access to -- required or optional.
>     I was maybe not clear enough. So here's in the example. Suppose
>     module A is a root module (the one mentioned in java -m option):
>     module A {
>         requires B;
>     }
>     ...searches for module B on -module-path and adds it to runtime
>     configuration, failing to start the program if B is not found. If
>     B is found it adds a read edge from A -> B.
>     module A {
>         requires optional B;
>     }
>     ... doesn't search for module B but still adds a read edge from A
>     -> B if B happens to be included in the configuration by some
>     other means. The 'other means' could be anything from:
>     - some other module that is already a part of configuration
>     "requires B" (say a root application module directly or a
>     transitive dependency)
>     - adding -addmods B command line option
>     - deployment descriptor of a .mwar application says so
>     I can certainly say that this is backward compatible in code. The
>     code stays the same.
>     I'm all *for* intorducing optional dependencies concept into the
>     deployment descriptor. It's just that I don't see -modulepath as
>     an equivalent to -classpath in the sense that optional dependency
>     should make module part of the configuration when it happens to be
>     searchable.
>     Regards, Peter
>>     Cheers,
>>     Paul
>>     On Fri, Dec 18, 2015 at 10:02 AM, Peter Levart
>>     <peter.levart at gmail.com <mailto:peter.levart at gmail.com>> wrote:
>>         On 12/18/2015 04:49 PM, Peter Levart wrote:
>>             You can check whether the optional module is included in
>>             a runtime configuration or not with a simple
>>             Class.forName() check even if you don't depend on the
>>             module (i.e. don't list it in "requires" descriptor at
>>             runtime). The visibility of classes is not restricted. It
>>             only depends on ClassLoader hierarchy. When you
>>             successfully resolve some optional class at runtime (with
>>             Class.forName), you then have to add a read edge to it's
>>             module:
>>                 Class<?> optionalClass = Class.forName("...");
>>             MySelfClass.getModule().addRead(optionalClass.getModule());
>>             ...before invoking any code that uses this module.
>>         Just had an idea!
>>         Optional dependency at runtime could add a read edge to the
>>         module if that module was included in the configuration, but
>>         would otherwise not cause that module to be included in the
>>         configuration by itself. How does that sound? Spring would
>>         work as before - no .addRead() calls needed. Just
>>         Class.forName("OptionalClass").
>>         Regards, Peter

More information about the jigsaw-dev mailing list