Open agentgt opened 1 year ago
Great comments and certainly raises points that I had not thought about - thanks for that!! I'll leave this issue open for other people who wander here to read etc.
For people who are not aware, this project was created to help with a discussion on the jigsaw-dev mailing list about this pattern and https://bugs.openjdk.org/browse/JDK-8299504 .How this pattern works in classpath, no longer works in module-path (hence the JDK bug logged), and what the options are for dealing with that for libraries that want to support both classpath and module-path).
I'll look to add a link to that jigsaw-dev discussion / thread some time.
Cheers, Rob.
Oh yes I forgot about that problem. Was it brought back up? I have been unsubscribed lately from the jdk dev mailing list.
Another issue with the module-info.java
that is apropo to our projects is you can't generate a listing of providers and concatenate them like you could with META-INF/services
. Well that I know of.
The META-INF/services
was an easy pseudo-non-reflection (it still is reflection but Graal VM native can use it as a hint as a reachable class) way to generate a list of generated classes. I suppose you bytecode could alter the module-info class file but that seems wrong.
One thing that module-info.java
provides
does have going for it (that few know about) is that you can use a static method called provider
instead of no-arg constructor. This I suppose slightly mitigates the extra jar problem you as don't need a proxy/forwarder/decorator type implementation (that would then call the other jars real implementation as I'm fairly sure you can't provides ... with
another class that isn't in your module... fairly sure).
Oh yes I forgot about that problem. Was it brought back up?
Yes, by me - https://mail.openjdk.org/pipermail/jigsaw-dev/2023-April/014846.html
you can use a static method called provider instead of no-arg constructor.
I only just saw that the other day. I'm wondering if that existed/works in Java 11 via classpath so looking to check that sometime. At the time it didn't look like a module-info only thing to me so I'll look to check that.
method called provider ... slightly mitigates the extra jar problem
As I see it no it won't help for this particular case. Ultimately the issue is that for provides <interface> with ...
that <interface>
type MUST be a class that exists and resolvable in module-path (unlike classpath where it is allowed to not exist). Ultimately, today this means that the provides ...
clause needs to move into another jar so that it is in a different module - which then guarantees that for module-path the service implementation is only accessible if the service interface type is accessible.
Its a solution that is growing on me each time I look at it :)
A future Java might support multiple modules in a single jar but that sounds like it would be quite some before before it arrives and can be adopted by libraries.
Hi Rob,
You are probably not looking for commentary on this but apparently I follow you and this popped up on my github recs... so here we go based on my experience:
I understand and agree multiple artifacts are painful particularly in the context of an application going full dependency inversion instead of a library. It is painful in almost any IDE to see 3 projects instead of just 1 (albeit Eclipse IMO much better than intellij on this because of its "Working Sets"). This is largely a waste because although the separation particularly compile time separation is good it is unlikely there will ever be multiple services/plugins.
However it should be noted in the context of libraries there are multiple implementations. Not just multiple implementations but possibly implementations that extend others.
The last sentence is important.
Let us take logback as an example. Let us say I want to make a new plugin SLF4J that extends logback. You cannot do it today because SLF4J only allows one implementation and unfortunately the logback does not have its implementation separated from the actual service registration (module-info and META-INF/servces.
Thus based on my experience ideally a library that wants to allow extending (perhaps through inheritance) have their plugin jar ONLY have the service registration (and corresponding class service provider implementation).
I guess what I'm saying is a problem with the ServiceLoader is that just by adding a jar you are opting in that it is the implementation but what happens if you just want to extend the implementation. Perhaps this is not a common use case but there have been many times I have wanted to wrap Logback but cannot.