Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8347915

Service use or provides in module creates required dependency

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 25
    • core-libs
    • None
    • minimal
    • Java API
    • SE

      Summary

      Extend the module system's support for optional dependences to allow for services that are optional. More specifically, allow for the resolution of a module that uses or provides a service if the module with the service was present at compile time but is missing at run time.

      Problem

      The module system allows a module to consume a service (uses p.S) whose implementation is provided by another module (provides p.S with ...). Service providers are inherently optional: there may be no modules at run time that provide an implementation of a given service. Consumer modules discover available implementations via the java.util.ServiceLoader API and routinely handle the scenario where zero implementations are available.

      The module system allows a module to specify a dependence that is mandatory at compile time but optional at run time. This is done with requires static. The motivation for this feature is mostly to let code have annotations that are inspected at compile time, such that the annotation interfaces need not be present at run time. However, the feature is sometimes used to depend optionally on a module that exports a service. In this case, the consumer module uses p.S and requires static <<the module which exports p>>. The consumer module must be coded carefully to handle the scenario where the optional module, and thus the service itself, are not present at run time. Additionally, or alternatively, a provider module provides p.S with ... and requires static <<the module which exports p>>.

      The module system does not support optional services. If a module uses or provides a service then the module with the service must be present at compile time and run time. Attempting to run with a missing service will fail eagerly at run time, as specified by a post-resolution consistency check in java.lang.module.Configuration.resolve.

      Solution

      Relax the post-resolution consistency check specified by Configuration.resolve to allow for a service that was present at compile time but missing at run time.

      Specification

      A new section "Optional Services" is added to java.lang.module.Configuration and the method description of java.lang.module.Configuration.resolve is changed to re-specify the post resolution consistency check.

      + * <h2><a id="optional-services">Optional Services</a></h2>
      + *
      + * Resolution requires that if a module {@code M} '{@code uses}' a service or
      + * '{@code provides}' an implementation of a service, then the service must be available
      + * to {@code M} at run time, either because {@code M} itself contains the service's
      + * package or because {@code M} reads another module that exports the service's package.
      + * However, it is sometimes desirable for the service's package to come from a module
      + * that is optional at run time, as indicated by the use of 'requires static' in this
      + * example:
      + *
      + * {@snippet :
      + *     module M {
      + *         requires static Y;
      + *         uses p.S;
      + *     }
      + *
      + *     module Y {
      + *        exports p;
      + *     }
      + *  }
      + *
      + * Resolution is resilient when a service's package comes from a module that is optional
      + * at run time. That is, if a module {@code M} has an optional dependency on some module
      + * {@code Y}, but {@code Y} is not needed at run time ({@code Y} might be observable but
      + * no-one reads it), then resolution at run time <i>assumes</i> that {@code Y} exported
      + * the service's package at compile time. Resolution at run time does not attempt to
      + * check whether {@code Y} is observable or (if it is observable) whether {@code Y}
      + * exports the service's package.
      + *
      + * <p> The module that '{@code uses}' the service, or '{@code provides}' an implementation
      + * of it, may depend directly on the optional module, as {@code M} does above, or may
      + * depend indirectly on the optional module, as shown here:
      + *
      + *  {@snippet :
      + *     module M {
      + *         requires X;
      + *         uses p.S;
      + *     }
      + *
      + *     module X {
      + *         requires static transitive Y;
      + *     }
      + *
      + *     module Y {
      + *         exports p;
      + *     }
      + * }
      + *
      + * In effect, the service that {@code M} '{@code uses}', or '{@code provides}' an
      + * implementation of, is optional if it comes from an optional dependency. In this case,
      + * code in {@code M} must be prepared to deal with the class or interface that denotes
      + * the service being unavailable at run time. This is distinct from the more regular
      + * case where the service is available but no implementations of the service are
      + * available.
      @@ -359,9 +358,16 @@
            *     that exports {@code p} to {@code M}. </p></li>
            *
            *     <li><p> A module {@code M} declares that it "{@code uses p.S}" or
      -     *     "{@code provides p.S with ...}" but package {@code p} is neither in
      -     *     module {@code M} nor exported to {@code M} by any module that
      -     *     {@code M} reads. </p></li>
      +     *     "{@code provides p.S with ...}", but the package {@code p} is neither in
      +     *     module {@code M} nor exported to {@code M} by any module that {@code M}
      +     *     reads. Additionally, neither of the following is {@code true}:
      +     *     <ul>
      +     *         <li> {@code M} declares "{@code requires static}" for at least one
      +     *         module that is not in the readability graph. </li>
      +     *         <li> {@code M} reads another module that declares
      +     *         "{@code requires transitive static}" for at least one module that is
      +     *         not in the readability graph. </li>
      +     *     </ul> </li>
            *
            * </ul>
            *

            alanb Alan Bateman
            webbuggrp Webbug Group
            Alex Buckley, Sundararajan Athijegannathan
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: