> If I had known this was going to turn into a debate I wouldn’t have
> responded to the
> question. But it seems either my response wasn’t clear, you did not
> understand
> what I wrote, or you have some preconceived notion as to why anything
> beyond
> ServiceLoader is needed.


I believe that a debate is something that helps clear  the details and is a
positive thing. I am not asking questions l'art-pour-l'art. I still think
that some of your arguments and reasonings could be reconsidered. By doing
so, I can help raising my concern, you can think about these and
answer those and the end result may be something better than a single sided
approach.

Contemplating about the reason why I was asking some of the questions is
counter productive and drives to a bad, feeling influenced direction. Do
not.


> I would suggest that before responding to this email that
> you go look at how log4j-plugins is implemented in the master branch.
>

Sure, if you propose to create a commons-plugin library that is an extract
of the plugin handling of log4j so that log4j next releases do not need to
keep the functionality inside log4j but rather as a dependency on this new
library. On the other hand, if the goal is to create something that is
useful generally then we should look at other solutions as well.


> From this it is clear that you completely misunderstand what the plugin
> system is doing.
>

That may really be very much true.


> First, the plugin system DOES use ServiceLoader. In fact, Log4j uses
> ServiceLoader
> in at least 7 different places. For one, it uses ServiceLoader to locate
> the Log4j
> implementation similar to how SLF4J does (although Log4j implemented it
> prior to SLF4J).
>
> Consider that you have 150 or so plugins, of which maybe only 10 will get
> used. But
> you don’t know beforehand which 10. ServiceLoader would have to load all
> 150 classes.


Not. It does not need to  create instances of all of them. This is what I
explained, and this is the reason why I explained it. JPMS or not, the new
ServiceLoader used by Java 9 and later will call the static factory method
of the class if that exists. Then the plugin can decide if it wants itself
to be instantiated or not. Somewhere there should be some logic that
filters 10 from the 150. If that is in a central place implementing some
industry-best-practice configuration based algorithm, or outsources the
decision to the plugins themselves should not make a big difference in
performance.

On  the second though, instantiating 150 lightweight classes must not be a
big burden. The ServiceProvider JavaDoc documentation suggest that services
should be implemented as proxies or factories instantiating their real
working class lazily in case the instantiation is costly.


> This is indeed very slow. Yes we have benchmarked it. But the Plugin
> system IS a
> Java Service. So instead, you need to only load 1 class for every jar that
> contains plugins.
> The result is that you only need to load 4 or 5 classes. This is
> considerably faster.
>

Yes, this is the approach where you insert another layer above the service
loader that does part of the job that the service loader can also do in a
different way. Essentially you let the plugin libraries, each containing
several plugin classes to implement their own service loaders.


> In addition, services loaded by ServiceLoader are singletons.


No, they are not. Every ServiceLoader instance will create new instances,
and even a single ServiceLoader can be asked calling the `reload()` method
to evict the instances from its cache and create new instances.


> It is not unusual to require
> multiple instances of.a Plugin so this would be difficult to do with the
> ServiceLoader.


The practice in that case is that the plugins implement a `List<S>`
interface and the instantiation or provider method returns the list of the
instances. I understand that this may not be something that one likes, but
it is not too complex and can be done.


> I’m not sure why you are explaining how ServiceLoader works. As I said, I
> am quite
> familiar with it.
>

Because you said things which are factually wrong, like services being
singletons.


> Nothing that helps. What ServiceLoader really does best is instantiating
> factories.
> You then use that factory to instantiate what you really want. Most uses
> of ServiceLoader
> in Log4j do that.
>

I get that, and I agree with that. This is how a plugin system is to be
designed.


> This is not opinion. This is a fact. Adding 50 entries to the service
> loader file is much
> more painful than adding just 1. There is no way you can argue against
> that.
>

If you say that adding 50 entries takes ten more minutes than adding one,
that is factual. "Painful" as an expression is opinion. It hurts you, may
not hurt others.

For example, when I develop a plugin I have to create a class, unit tests,
mocking the environment. documentation and so on. Adding an extra line to
the META-INF/services comparing to the time needed to develop the plugin
itself is negligible. Adding 50 lines comparing to the time needed to
develop 50 plugins is the same ratio.

That is not correct. That may be true when using the module path but the
> javadoc
> for ServiceLoader is quite clear that the file is still required for jars
> on the classpath.
> Since the vast majority of Java users do not use JPMS this isn’t really
> helpful. I
> should also note that in fact the opposite is true. If your jar is an
> automatic module
> then JPMS will create the provides statement for you based on the presence
> of the
> META-INF/services file.
>

Perhaps developing a commons-plugin system is a good point to require
application developers and plugin developers to use the module system.


> Again, I would suggest you look at the log4j-plugins implementation before
> making sweeping statements such as this.
>

I am not an expert about log4j and the plugin system of it,which you are.
>From this distance it seems that log4j uses factories for the plugins as
services or builders in case there is a need for some configuration. In
case of the builders the configuration parameters are injected that way
this plugin system implements a simple DI framework like Plexus, Pico,
Guava, Spring instead of using one. With the factory approach it does the
same as the JDK ServiceLoader calling the `provider()` method.

Again, if you find that answering the questions is difficult there may be
several reasons. One thing is for sure: I am not trolling you. I am asking
these questions because I honestly believe that any new library should
address the things that are not addressed by other systems and libraries,
and should provide a better way to do things, otherwise they will not be
widely used.


-- 
Peter Verhas
pe...@verhas.com
t: +41791542095
skype: verhas

Reply via email to