core: Add support for ServiceLoader to the Core Framework
We have a Service Loader Mediator spec. But it is not built into the framework and currently depends upon weaving.
I would like to explore adding support directly unto the framework for the Service Loader model. JPMS has direct support for the Service Loader model via uses and provides in the module-info file. JPMS has advantages since it is built into the java runtime, so we may not be able to do as well. But I suspect we can do better than the current Service Loader Mediator spec by building this function into the core framework.
I would support that as well, because the ServiceLoader Mediator requires its Capabilities to work properly. Especially Jarkarta API's (JPA, JAXB, Jax-Ws, Websockets) make use of the ServiceLoader to find the Implementation. The OSGi Manifests often event dont have the Capabilities or they are not complete. Having this support in the core framework, would solve major pain points.
We have a Service Loader Mediator spec.
I once tried to use that but it seems not fitting very well because it seem to be limited to the use of ServiceLoader.load() calls but I must confess I never wanted to use it that way but the other way round: Accessing ServiceLoader specified services in an OSGi way
But I suspect we can do better than the current Service Loader Mediator spec by building this function into the core framework.
I once written a extender-bundle that simply discovers SPI in META-INF/services and registered them as plain OSGi services that's quite useful and could even be made lazy when using a ServiceFactory.
Especially Jarkarta API's (JPA, JAXB, Jax-Ws, Websockets) make use of the ServiceLoader to find the Implementation.
Jakarta can uses an OSGi-aware serviceloader that works quite well. I just always wondered why they did not simply delegate to standard java ServiceLoader.load() if nothing is found (it instead returns null then) this requires some care on the caller-side, but maybe this can server as an inspiration?
So if the osgi.util would contain such an ServiceLoaderHelper that OSGi could call to fnd SPIs in a standard compliant way that would be great.
Service Loader Mediator automatically makes services OSGi service already provided you set the register directive which includes the type, which @ServiceProvider does for you. Since the spec lets you add arbitrary service properties via the Capability so does SPI Fly as does @ServiceProvider. Finally Aries SPI Fly let's you make prototype scope services by adding the property service.scope=prototype?
Furthermore, since the last few versions SPI Fly can be used without metadata in the provider/consumer bundles in question. You can force bundle(s) which do not have SLM requirements or capabilities using framework properties:
org.apache.aries.spifly.auto.consumers=<comma_delimited_bsn_globs>
org.apache.aries.spifly.auto.providers=<comma_delimited_bsn_globs> #here you can add service properties using OSGi package attribute syntax
All this needs better docs for sure.
@rotty3000 probably yes... I just failed to get it setup and the aries stuff often pulls in a lot of stuff, much more effort I want to spend for a simple lookup :-)
At least this "automatically makes services OSGi service already provided" has not worked well starting without a managed setup (e.g. karaf).
SPI Fly can have as little as itself and OSGi as a dependency. (See org.apache.aries.spifly:org.apache.aries.spifly.dynamic.framework.extension:1.3.4). You do not need a managed setup for everything described above. You do however have to have the correct metadata.
@rotty3000 I'll give it another try nex time it becomes relevant, maybe I can use this for pax-jpa as well, maybe its just a matter of
this needs better docs for sure
are you a developer of the spi-fly project as well?
yes I am, sadly I'm not in love with the tech Aries has migrated to for documentation. I find it very painful and this didn't help the fact that a lot of Aries docs were already extremely out of date. But that isn't your problem and it's not an excuse for poor docs...
@rotty3000 currently using JAXB in OSGi requires an OSGi-aware serviceloader do you think you can help the eclipse-ee4j people to add appropriate headers so it works with the spifly instead?
I'm also interested in replacing pax-jpa tracker with using spifly would that be possible?
The bundle simply needs every item declared in META-INF/services/javax.persistence.spi.PersistenceProvider as PersistenceProvider service.
Hey @laeubi sorry for the delayed answer but I wanted to make a first pass to fix the SPI Fly documentation [1] so that I could use it to answer your question :D
Please review it to see if that helps you with JAXB (it's not very long). I've been using SPI Fly's auto properties [2] to handle JAXB in Aries JAX-RS whiteboard [3] successfully ever since this was implemented. In other words I didn't go the route of modifying the JAXB API or Implementation to add SLM requirements&capabilities but I still get a working system.
[1] https://aries.apache.org/documentation/modules/spi-fly.html [2] https://aries.apache.org/documentation/modules/spi-fly.html#_dynamic_weaving_by_auto_properties [3] https://github.com/apache/aries-jax-rs-whiteboard/blob/master/jax-rs.itests/itest.bndrun#L55-L56
No problem, I'll try to give it a try the next days, the documentation is much clearer now I think. I'm just a bit uncertain about JAX weaving versus the OSGi-Serviceloader, but this sounds interesting for cases where the consumer is not aware of OSGi..
There is just one use-case I feel missing (I hope it is ok to discuss this in the context of this issue, if not let me know a better place):
According to the docs I need to provide some framework properties, this seems rather "static" and I need to know the name of the bundles beforehand, also I don't see a way to limit the registration to some SPI interface.
What would be useful I think would be the following:
- I can define a Requirement in the Bundle-Manifest e.g. Require-Capability: java.util.ServiceLoader:="(service=javax.persistence.spi.PersistenceProvider)" (I hope I got the syntax right from here so feel fre to correct me if I'm wrong)
- Aries SPI-Fly would detect that header, track all bundles in the framework for any
META-INF/services/javax.persistence.spi.PersistenceProviderand registers a ServiceFactory for each whosegetServicereturns the instance (andnullfor all other bundles without that header)
Hi @laeubi I think this is an interesting conversation. Could we take over to the Aries dev mail list or possibly in Aries JIRA?
I have created https://issues.apache.org/jira/browse/ARIES-2071
Error executing command: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=swiggy-feature; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=swiggy-feature)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve swiggy-feature/1.0.0.SNAPSHOT: missing requirement [swiggy-feature/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=org.apache.geronimo.specs.geronimo-jpa_2.2_spec; type=osgi.bundle; version="[1.1.0,1.1.0]"; resolution:=mandatory [caused by: Unable to resolve org.apache.geronimo.specs.geronimo-jpa_2.2_spec [203](R 203.0): missing requirement [org.apache.geronimo.specs.geronimo-jpa_2.2_spec [203](R 203.0)] osgi.serviceloader; (osgi.serviceloader=javax.persistence.spi.PersistenceProvider)]]
how to solve this error iam working on with the open jpa it requires the geronimo and the geronimo pom.xml has the require capability of osgi.serviceLoader
@rotty3000 @bjhargrave @laeubi @maho7791 how to solve this
@muthukumar1756 - please open a new issue for usage questions. This issue is a design discussion for a new feature in the OSGi core specification.