Issue #ServiceLoaderEnhancement
Ali Ebrahimi
ali.ebrahimi1781 at gmail.com
Thu Jul 14 04:31:21 UTC 2016
Hi,
I suggests add ranking support for prioritizing service providers as OSGI
do.
provides com.services.api.MyService with
com.services.impl.MyServiceIMPL rank 10;
On Wed, Jul 13, 2016 at 10:36 PM, <mark.reinhold at oracle.com> wrote:
> 2016/7/1 2:27:39 -0700, Stephen Colebourne <scolebourne at joda.org>:
> > The ServiceLoader API is to be pushed as a key class by the module
> > system. This issue is proposing enhancements to the API. Others may
> > want to add their own proposals.
> >
> > Currently, ServiceLoader requires service implementations to have a
> > public no-args constructor on a public class. This is very
> > restrictive, especially in a Java 8 world of immutable classes and
> > factory methods (with constructors actively avoided).
> >
> > JSR-310 has a service for loading Chronology implementations. In
> > ThreeTen-Extra, I have a number of additional implementations [1].
> > Unfortunately, all the implementations are forced to have a public
> > no-args constructor, as ServiceLoader cannot make use of the singleton
> > INSTANCE constant. As can be seen, I have to mark the public no-args
> > constructor as deprecated [2]. This state of affairs is frankly
> > ridiculous, and is one of the reasons putting me off using
> > ServiceLoader non-JDK code.
> >
> > I propose that the spec of ServiceLoader is extended to make it more
> useful.
> >
> > Firstly, I propose that all reflection by ServiceLoader should use
> > setAccessible(true) to allow providers to be non-public.
>
> We could do this for service providers defined in modules, but not for
> those specified via the META-INF/services convention. The problem with
> the latter is that if ServiceLoader could instantiate an arbitrary
> non-public class then an adversary could spoof it into doing that simply
> by placing an appropriate META-INF/services configuration file on the
> class path. That's not possible for providers in modules, since the
> declaration of the provider and the provider itself are always tightly
> associated with each other, in the same artifact, so we can relax the
> restriction in that case.
>
> > Secondly, I propose that if no public no-args constructor is found on
> > the provider class, ServiceLoader should locate a public static
> > constant named "INSTANCE" and use that instead.
>
> That's reasonable, though we don't have much precedence for name-based
> conventions in the SE platform itself.
>
> > This proposal could be extended further. Instead of searching for
> > "INSTANCE", it could look for all public static constants of the
> > provider type, allowing one provider class to result in many provider
> > instances.
>
> I suspect that might be one heuristic too much. I could see searching
> for INSTANCE, and maybe also INSTANCES where the latter refers to an
> array or a collection of appropriate type, but just taking anything based
> solely upon type matches could lead to difficult-to-diagnose failures.
>
> An alternative is to take an explicitly-declarative approach, defining
> something like a @Provides annotation to identify the constructors,
> factories, or fields that construct or contain actual provider objects.
> I'll give this some thought.
>
> > Thirdly, it should be possible to access the set of provider classes
> > without instantiating them. This would allow applications to use the
> > module-info design for services without using ServiceLoader, eg to
> > reflect on the provider classes, perhaps to search for annotations.
>
> As an historical note, the original idea way back in Java 1.3 was for
> complex providers to be represented by small, lightweight proxy objects
> rather than full providers, or types. To quote the specification (of
> the sun.misc.Service class, before it became java.util.ServiceLoader):
>
> * ... This <i>provider class</i> will typically not be the
> entire
> * provider itself but rather a proxy that contains enough information to
> * decide whether the provider is able to satisfy a particular request
> together
> * with code that can create the actual provider on demand. The details of
> * provider classes tend to be highly service-specific; no single class or
> * interface could possibly unify them, so no such class has been defined.
>
> Most of the services defined and used in the JDK itself follow this
> advice, but I accept that many others out in the world do not, so at
> this point people reasonably want to be able to filter providers based
> on types and annotations thereon. This should be straightforward; I'll
> work up a proposal.
>
> > I hope this proposal is given serious consideration, as at present the
> > design of ServiceLoader is simply too restrictive to be appropriate to
> > be hard coded into the module specification.
>
> These are all good suggestions; thanks for raising them here. I've added
> them to the issue list:
>
>
> http://openjdk.java.net/projects/jigsaw/spec/issues/#ServiceLoaderEnhancements
>
> - Mark
>
--
Best Regards,
Ali Ebrahimi
More information about the jpms-spec-observers
mailing list