2014-12-14 0:25 GMT+01:00 Romain Manni-Bucau <firstname.lastname@example.org>:
> I saw in several projects this kind of pattern:
> Singleton.get()/Singleton.set(Instance) // replace the SPI. set() can
> throw an exception if already set, I would just log a warn/err but not
I personally do not like this pattern much. I would prefer a clear API
that is free of such initialization things. Using ServiceLoader and on top
reading a system property would work as well in most cases.
But one aspect where I have to say, has its pros, is that you can add any
kind of complexity of initialization on top of it, instead of being stick
to exactly one kind of root initialization.
> Then Singleton.get() returns a Context. Then Context has a
> ServiceResolver. Then ServiceResolver has a T getService(Class<T>). If
> you need a list of service you define a dedicated service
> (FormatsProvider.getFormats() or PropertySources.getSources() for
Pros and Cons I see here. Pro: the spi and the debugging
would be possibly easier. Con: you probably duplicate the loading code for
services mutliple times for each, whereas I would expect the loading
policy to be unified for a certain runtime (eg if I support loading SPIs
from CDI I would expect this is the case for all kind of SPIs in my system,
not only for some).
> In sumarry the singleton allows to define a behavior for the current
> environment (EE, standalone, OSGi etc...) then Context represent
> current app services.
Agree, that is what currently Bootstrap (via ServiceProvider) does.
> The good point is you can get rid of classloader assumptions (which
> will never be portable or even work - see deltaspike
> BeanManagerProvider if you doubt of it) simply providing a container
> specific implementation without impacting apps/extensions themself if
> tamaya is provided by the container - which will hopefully be the case
> after some work ;).
So summarizing, I would propose:
1) Rename *Boostrap *to *Singleton*
2) Rename the (existing) *Singleton.init(ServiceProvider) *method to
* Singleton.set(ServiceProvider)*, writing a warning if one is already
(currently it throws an error).
3) Let all backing calls go to* Singleton.get(SPIClass.class)* instead of
static instance variables
holding the loaded backing beans, making CDI
support (and testing)
4) If no *ServiceProvider *was registered using* set(ServiceProvider) *I
fallback to the *ServiceLoader *based version and additionally write an
that the default loading is in place. This will make it work OOTB in
scenarios, but with the INFO log developers also some hint that they
running on defaults...
5) I would not add additional services just for asking for collection of
but keep the *public static <T> Collection<? extends T>
* serviceType)*on *Singleton*.
6) Perhaps we should also rename *public static <T> T getService(Class<T>
serviceType) *to *getSingleton(...)* ?