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