Automodules

Robert Scholte rfscholte at apache.org
Mon Feb 13 20:54:57 UTC 2017


On Mon, 13 Feb 2017 16:59:44 +0100, David M. Lloyd  
<david.lloyd at redhat.com> wrote:

> On 02/11/2017 10:18 AM, Robert Scholte wrote:
>> There are clearly 2 kinds of jars in play here: dependencies and
>> end-products.
>>
>> To have a reliable end-product you want to specify *every* requirement
>> and in this case it doesn't matter that a dependency has no official
>> module name, as long as you can specify and refer to it as a  
>> requirement.
>>
>> To have a reliable dependency you can only depend on named modules. Up
>> until now it is required to specify all requirements or do some command
>> line argument magic to compile or run such project.
>>
>> What I would like to achieve is to have a situation where end-products
>> can never be used as a dependency, because that would allow auto
>> modules, which makes it again unreliable as dependency.
>
> We accomplished exactly these goals in jboss-modules, simply by having  
> multiple "worlds": The module world itself (of course), and separated  
> worlds for the modularized class path or -jar command line.
>
> In the raw class path situation, we create a single module for the  
> entire class path.  This is essentially an "unnamed" blob, which can  
> consume available modules but cannot in turn be consumed by them.  This  
> allows a first step into the module world by allowing (over time) the  
> user to move modules from the class path into the module space as their  
> dependencies can be correctly and specifically analyzed (in other words,  
> it's one step from sloppy class path to constrained/clean module).  
> Classpath JARs could also be separated into modules which have a mutual  
> dependency mesh (assuming that circular dependencies are allowed),  
> allowing for a better diagnostic identity than just "classpath" (for  
> example).
>
> In the -jar situation, we create a module per JAR using the JAR's  
> Class-Path MANIFEST.MF header as the linking mechanism.  In the  
> container we also support the old extensions mechanism (which it turns  
> out is actually a pretty good basic module system in its own right).  In  
> this way, JARs are isolated from one another, consuming only what is  
> explicitly declared.  In the Java EE container, these dependencies are  
> usually transitive due to some unfortunate specification language, but  
> on the command-line they are not, which further improves isolation.  In  
> this case as well JARs can depend on modules but not vice-versa.  
> Circularity is also historically allowed in this situation.
>
> I have found these mechanisms to be more than adequate for providing an  
> easy on ramp for modularization, and neither one requires module name  
> fudging; in fact, mangling of names is harmful since it takes the  
> intuitive "my-project-1.3.3.jar" that would appear in diagnostics, which  
> can be copied and pasted into a "find" command for example, and turns it  
> into something rather unintuitive.  Having a modular classpath in fact  
> is the easiest possible "small" step because it allows code to run under  
> the new module accessibility and (service) loading rules without  
> otherwise affecting class loading behavior in any way.
>
> This is why I'm frustrated with automatic modules: they just don't seem  
> necessary, and have several proven problems which also seems to make  
> them insufficient.
>

Nice to know that my thoughts are confirmed with an existing modular  
system.
And the "small" step as adding one requirement at the time to a named  
module fits very well with the Maven eco system.

thanks,
Robert

>> Specifying a dependency is done by referring to the name of a module.
>> So what if we say that a end-product doesn't have a name anymore or that
>> it is not a module anymore. In that case it cannot be used as dependency
>> AND we could allow automodules in such case.
>>
>> In case of a dependency or named module you can only refer to other
>> named modules. All other required jars should be picked up from the
>> classpath, preferably by default.
>>
>> This is just a start, but would probably match most requirements from
>> both camps.
>>
>> So an example of the end-product jar:
>>
>> final myapp { // 'module' replaced with 'final'
>>     requires mylib;             // a named module, assume part of Maven
>> multimodule project
>>     requires java.base;         // a named module, part of Java
>>     requires java.sql;          // a named module, part of Java
>>     requires jackson.core;      // an unnamed module, name extract from
>> filename (jackson-core-2.6.2.jar)
>>     requires jackson.databind;  // an unnamed module, name extract from
>> filename (jackson-databind-2.6.2.jar)
>> }
>>
>> or
>>
>> module { // remove the name, so can never refer to it
>>     requires mylib;             // a named module, assume part of Maven
>> multimodule project
>>     requires java.base;         // a named module, part of Java
>>     requires java.sql;          // a named module, part of Java
>>     requires jackson.core;      // an unnamed module, name extract from
>> filename (jackson-core-2.6.2.jar)
>>     requires jackson.databind;  // an unnamed module, name extract from
>> filename (jackson-databind-2.6.2.jar)
>> }
>>
>> An example of the dependency jar
>>
>> module org.joda.convert {
>> //  requires ??guava??; no named module yet, will be picked up from
>> classpath
>> }
>>
>> other projects could already refer to org.joda.convert if they want to.
>> Once guava is a named module, org.joda.convert can specify it.
>>
>> regards,
>> Robert


More information about the jpms-spec-experts mailing list