Still driving off the cliff

Rémi Forax forax at univ-mlv.fr
Wed Feb 22 10:05:16 PST 2012


On 02/22/2012 06:39 PM, David M. Lloyd wrote:
> I disagree entirely with this entire line of thinking.  A Java module 
> system should NOT be about writing a container which resolves 
> dependencies and injects values!  The Java world does not need yet 
> another OSGi or yet another IoC container.
>
> And the Java world definitely DOES NOT need a module system that 
> requires special tools and indexes in order to install and run 
> anything!  What is the precedent in other languages?  Who would 
> possibly want this kind of API?  End users just want to be able to say 
> "I need these modules".  They don't want to detect service 
> implementations from their capabilities, they just want to say "give 
> me this implementation".  And they definitely don't want their 
> application blindsided by globally installed services!
>
> This reminds me so much of JUL, where a complete API was designed and 
> implemented without even talking to anyone who actually has experience 
> with logging frameworks.  The end result is an API that nobody uses 
> and everyone has to work around.  Guys, *think* about the end user.
>
> The end user wants to be able to install and use modules without any 
> special tools required, just like most other languages.  The end user 
> wants to be able to overlay their own modules in their home 
> directories, just like most other languages.  The end user wants to be 
> able to have application-specific module collections for their 
> application, just like most other languages.
>
> The user does NOT want to do a lot of configuration to get a module 
> off the ground.  The user can *understand* the concept of a class's 
> initiating class loader if you *let* them.  Service loading should 
> normally be relative to the module that is doing the loading, or the 
> application which is being run, *at the user's option*.  Let them 
> specify the class loader they want to load relative to.  It works 
> well, we've used that technique extensively and people seem to 
> understand it.
>
> We have *never* found an effective and robust use for 
> provides/requires capabilities in the real world - there's always a 
> price to be paid which could have been avoided using a simpler solution.
>
> Think simplicity, think determinism, think bottom-up design.  We don't 
> need more abstractions and rules, we need fewer!  By having each 
> module import only the modules it uses (including, if desired, 
> implementation modules for services), ServiceLoader continues to work 
> excellently *as it is today* with no modifications whatsoever!  In 
> other words, yes ServiceLoader handles that just fine as it is today!
>
> Let the *user* decide the scope for searching for service 
> implementations.  Even TCCL, much maligned as it is, is still 
> effective (arguably a hell of a lot more so) in a simple modular 
> environment, if only as an indicator of what application module is 
> being executed.  This is completely and perfectly aligned with its use 
> in JavaEE.  Having API variants which use TCCL and explicit class 
> loader specification is perfectly reasonable and entirely regular.
>
> It's one thing to acknowledge that certain design decisions were 
> possibly mistakes.  But it's another to deal with that fact by 
> pretending they never happened.  JavaSE as it is right now is not 
> perfect but existing infrastructure can be leveraged a lot more than 
> it is by Jigsaw, and to much better effect I might add.
>
> I know none of you guys really take JBoss Modules seriously but 
> *please* do so.  It is a very realistic, powerful, performant, and 
> effective depiction of what an SE module system could be.  It's out 
> there in the wild, and it works very well, leveraging existing 
> concepts such as TCCL and explicit class loader specification.  No new 
> service loader implementations are wanted or needed.  At least, not 
> with a module system as its excuse.
>
> Would my ideal SE module system look exactly like JBoss Modules?  No 
> way - there are definitely things I would want to do differently in 
> the JDK.  But the *concepts* are proven to be powerful and effective.  
> And those critical concepts do not include provides/requires 
> resolution OR global module or package registries OR special 
> installation tooling OR any language changes whatsoever!  So lets not 
> pretend that *any* of that is needed to make a module system that is 
> fast and effective.  In fact you can add to the features list "easy to 
> use", "manageable without special tooling", and "completely 
> customizable".
>
> You don't have to throw away every existing concept every time you add 
> a new one.  It's far better to find what already exists that fits in 
> to your new idea - and let me tell you, the more that fits, the 
> better, because you'll have happier users who have a better idea of 
> what the hell is going on.  This service loader thing is just the 
> latest example of you guys running amok with unnecessary new 
> concepts.  Why reinvent this particular wheel, when a module system is 
> all you need to make the old one work to its fullest potential?

David,
you have my vote on this issue.

ServiceLoader API is enough.

cheers,
Rémi

>
> On 02/22/2012 11:14 AM, Jaroslav Tulach wrote:
>> Hello David.
>>
>>> ## 20. 2. 2012 15:06:19 ##<
>>> 1) There is only one implementation which is used system-wide (this is
>>> your "services as singletons" scenario).
>>
>> Given your following comment ...
>>
>>> If a service is indeed a true singleton
>>> in every sense (which corresponds to case #1), then the simplest
>>> solution is to have the API import its implementation (or at least
>>> import its services resources in order to be able to locate it) and use
>>> its own class loader to locate it.
>>
>> ... I don't think this is injectable singleton example. Of course if 
>> you have
>> a singleton and it is supposed to have just a single implementation, 
>> then let
>> the API instantiate the implementation using "new". You can even put the
>> singleton API and its implementation into the same module. No reason 
>> to have
>> anything modular, imho.
>>
>>> 2) There are multiple implementations, however normally only one
>>> implementation is selected for the entire application.
>>
>> This is probably what I call injectable singleton:
>> http://wiki.apidesign.org/wiki/Injectable_Singleton#Initialize
>>
>> In contrast to case #1 it makes sense to use modularity here and 
>> separate the
>> singleton API into one module and put the implementation into other(s).
>>
>>> 3) There are multiple implementations, but each module may need to
>>> choose a different implementation.
>>
>>> If a service is typically per-module (case #3) then each module would
>>> import (at run time) its preferred implementation and use its own class
>>> loader to search for it.
>>
>> It will be better if the classloading tricks are eliminated as Jesse 
>> and Alan
>> wrote. Imho it may be sufficient to get all instances in the system and
>> somehow select the right one by querying its capabilities (e.g.
>> getSupportedXYZ(), etc.).
>>
>>> 4) There are multiple implementations, however implementations carry
>>> semantic meaning and generally must therefore be selected by some
>>> identifier.
>>
>>> Note that this case is unique in
>>> that the conceptual service dependency is not just a base type to be
>>> implemented, but it also has a "flavor" component to specify behavior
>>> characteristics.
>>
>> Actually NetBeans has an example of this style as well. The editor 
>> guards API
>> http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-
>> guards/overview-summary.html
>> benefits from the fact that requires/provides are just string tokens 
>> (not a
>> class names). One registers the service capable to work for Java and 
>> then uses
>>
>> provides token org.netbeans.api.editor.guards.Java;
>>
>> Users of the editor guards API wanting to deal with Java then use:
>>
>> /* guarantees editor guards API is on classpath */
>> requires org.netbeans.api.editor.guards;
>> /* guarantees the Java implementation will be found using 
>> ServiceLoader */
>> requires token org.netbeans.api.editor.guards.Java;
>>
>>> If a service's behavior varies by implementation (case #4), as is the
>>> case for cryptographic, digest, and other security APIs (where the
>>> algorithm is significant to determining the behavior of the
>>> implementation) and several third-party APIs, then the application must
>>> import the implementations which it uses
>>
>> A cryptography module providing SHA implementation would use 
>> something like
>>
>> provides token java.security.MessageDigest.SHA
>>
>>> All of these solutions have in common that the API to locate the
>>> implementation requires some notion of what class loader to search.
>>
>> I don't think so. You can enumerate all implementations. Sure, it 
>> would be
>> more efficient to prevent instantiating unneeded classes and select 
>> just the
>> right one, but that is something ServiceLoader does not handle[1] in 
>> general,
>> as far as I can tell.
>>
>> -jt
>>
>> [1] One of the reasons NetBeans use Lookup which can handle declarative
>> services as demonstrated at 
>> http://wiki.apidesign.org/wiki/CompileTimeCache
>>
>
>




More information about the jigsaw-dev mailing list