Proposal: #AutomaticModuleNames (revised)

mark.reinhold at oracle.com mark.reinhold at oracle.com
Thu May 4 17:38:32 UTC 2017


Issue summary
-------------

  #AutomaticModuleNames -- Revise the algorithm that computes the names
  of automatic modules to include the Maven group identifier, when
  available in a JAR file's `pom.properties` file, so that module names
  are less likely to collide, or else drop the automatic-modules feature
  entirely, since it may be more trouble than it's worth.  [1]

Proposal
--------

  - Do not drop the automatic-modules feature.  It's a critical part of
    the overall migration story: It allows application developers to
    get started modularizing their own code without having to wait for
    all of the libraries and frameworks that they use to be modularized.
    Popular libraries and frameworks that are actively maintained will
    hopefully be modularized fairly soon, but less-active projects will
    take longer -- perhaps years or even decades -- and many inactive or
    abandoned projects will never be modularized.  This feature has been
    well-received by a wide variety of developers despite the fact that
    some expert users are not comfortable with it.

  - Define a JAR-file manifest attribute, `Automatic-Module-Name`, whose
    value is used as the name of the automatic module defined by that JAR
    file when it is placed on the module path, as previously suggested
    [2][3].  If a JAR file on the module path does not have such a
    manifest attribute then its automatic-module name is computed using
    the existing filename-based algorithm.

    The name of this attribute is now `Automatic-Module-Name` rather than
    `Module-Name`.  The former makes it clear that if a JAR file on the
    module path contains both an `Automatic-Module-Name` manifest
    attribute and an explicit `module-info.class` file then the manifest
    attribute is irrelevant, because the module defined by the JAR file
    is explicit rather than automatic.  `Module-Name` would also suggest
    that there are `Module-Exports` and `Module-Requires` attributes,
    which there are not.

    With this mechanism a library maintainer can claim a stable module
    name with very little effort; in Maven, e.g., a manifest attribute
    can be added in just a few lines of a project's `pom.xml` file.  A
    library maintainer can claim a stable name early, before all of the
    library's dependencies are modularized, which will allow libraries
    and applications that depend upon it to be modularized immediately.
    A user of a library can suggest a stable name to the library's
    maintainer, and easily submit a patch that implements it.  This will
    enable the uncoordinated modularization of libraries across the
    entire ecosystem.

  - Strongly recommend that all modules be named according to the reverse
    Internet domain-name convention.  A module's name should correspond
    to the name of its principal exported API package, which should also
    follow that convention.  If a module does not have such a package, or
    if for legacy reasons it must have a name that does not correspond to
    one of its exported packages, then its name should at least start
    with the reversed form of an Internet domain with which the author is
    associated.

  - Make sure that developers are aware of the risks of publishing, for
    broad use, explicit modules that require automatic modules.  An
    automatic module is unreliable, since it can depend on types on the
    class path, and its name and exported packages could change if and
    when it's converted into an explicit module.  It's fine to declare
    and use explicit modules that require automatic modules in limited
    settings.  If you publish such a module to, e.g., Maven Central, then
    you must be prepared to revise both the declaration and content of
    your module as its dependencies are modularized over time.  This may
    have an adverse impact on the users of your module, especially if
    your module `requires transitive` an automatic module.

The following three points are essentially unchanged from the first
proposal [4]:

  - Do not revise the algorithm that computes the names of automatic
    modules.  The suggestion to use Maven coordinates when available [5]
    would help less than half of the most popular projects in use today,
    as determined by three different surveys.  It would result in module
    names that are often annoyingly verbose and known to be objectionable
    to some module authors, and it would raise non-trivial issues with
    regard to standardization and convention.  The names generated by the
    current algorithm do not follow the reverse-DNS convention, but they
    are at least easily derivable from the name of the original JAR
    files.  [6]

  - To increase awareness of when automatic modules are used, and of the
    consequences of their use, suggest that Java language compilers issue
    two new types of warnings, and implement these warnings in the RI:

      - An opt-in (i.e., off-by-default) warning on a reference to
        an automatic module in a `requires` directive in a module
        declaration, and

      - An opt-out (i.e., on-by-default) warning on a reference to
        an automatic module in a `requires transitive` directive in
        a module declaration.

    The first warning allows developers to be maximally hygienic if they
    so choose.  The second helps make the author of an explicit module
    aware that they're putting the users of that module at risk by
    establishing implied readability to an automatic module.

  - Encourage Java run-time systems to make it easy to identify via,
    e.g., command-line options, which observable modules are automatic,
    which observable modules would establish implied readability to
    automatic modules if resolved, and which automatic observable modules
    are actually resolved.  Implement these capabilities in the RI.

Notes
-----

This revised proposal is informed by a vigorous discussion on the OpenJDK
jigsaw-dev mailing list [7] of the first proposal [4].  Two things became
clear in that discussion, and in related discussions triggered by it.

First, after twenty years the reverse-DNS naming convention is deeply
ingrained in the minds of most Java developers.  Stephen Colebourne made
a clear and passionate case for it [8] and many developers voiced support
for his argument, both on Twitter and elsewhere.  Some people may prefer
shorter, project-oriented names, and those can be fine to use in limited
projects that will never, ever see the light of day outside of a single
organization.  If you create a module that has even a small chance of
being open-sourced in the future, however, then the safest course is to
choose a reverse-DNS name for it at the start.

Second, the fact that the name and effective API of an automatic module
are inherently unstable is less of a problem than I previously thought
[9][a].  Developers who use Maven and related tools, such as Gradle --
which is most developers -- are used to coping with breakage when they
upgrade the dependencies of a project to a newer version [b][c].  If the
name or effective API of an automatic module change, either when its
maintainer adds an `Automatic-Module-Name` attribute or writes an
explicit `module-info.java` file, then the maintainers of projects that
use that module will just fix any problems that they encounter when they
upgrade.

After thinking about the first observation I'm now convinced that if
tools insert `Automatic-Module-Name` manifest attributes then they will
only do so when the module names that they define follow the reverse-DNS
convention, since to do otherwise would go against what most developers
strongly prefer and expect.  After thinking about that and the second
observation I hereby retract [d] my previous advice [9] that automatic
modules should not be given stable names.

                                  * * *

In related threads on jigsaw-dev both Stephen Colebourne [e] and Robert
Scholte [f] suggest a new kind of explicit module, variously called
"partial" or "incomplete" or "soft", which can read all unnamed modules
so that dependencies that have not yet been modularized can be left on
the class path.  This is an attractive notion on the surface, and in fact
one that we partly implemented in the prototype code base over two years
ago, using the term "loose".  We didn't pursue it then, however, and I
don't think it's worth pursuing now, for two reasons:

  - If "partial" (or whatever) modules were to replace automatic modules
    then application developers would have to wait until all of their
    dependencies have been at least "partially" modularized before they
    can even begin to experiment with modularizing their own code.

  - We could solve that by keeping automatic modules and adding partial
    modules, but then we'd have a more complex module system and a more
    complex story to tell.  To consider just one possible question,
    should developers go ahead and use their dependencies as automatic
    modules, or wait for them to become named automatic modules, or wait
    for them to become partial modules?

The `Automatic-Module-Name` manifest attribute is, from a technical
standpoint, aesthetically unpleasant since it defines a second way
to name modules.  Taken alone, however, it does enable uncoordinated
modularization using stable module names with little effort, and so
it appears to be the least-bad option on the table.


[1] http://openjdk.java.net/projects/jigsaw/spec/issues/#AutomaticModuleNames
[2] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2017-February/000582.html
[3] http://openjdk.java.net/projects/jigsaw/spec/issues/#ModuleNameInManifest
[4] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2017-April/000667.html
[5] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2017-January/000537.html
[6] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2017-April/000666.html
[7] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/thread.html#11955
[8] http://blog.joda.org/2017/04/java-se-9-jpms-module-naming.html
[9] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2017-April/000682.html
[a] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012304.html
[b] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012327.html
[c] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012335.html
[d] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012367.html
[e] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012370.html
[f] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012399.html


More information about the jpms-spec-experts mailing list