Thanks Dirk,
Indeed, fully agree.
Thanks for your link to the corresponding chapter in the spec.
I knew about the standard approaches with trackers etc, but these are too complex and AFAIK do not work well with prototype-scoped services.
It seems I definitely need to look at how to apply ServiceObjects, for use by non OSGi-experts when integrating between OSGi services and legacy.
erwin.
From: osgi-users-bounces@xxxxxxxxxxx <osgi-users-bounces@xxxxxxxxxxx> On Behalf Of Fauth Dirk (XC-ECO/ESM1)
Sent: Friday, 8 January 2021 10:52
To: This is a community mail list for OSGi technology. Any OSGi technical discussion or questions are acceptable here. <osgi-users@xxxxxxxxxxx>
Subject: Re: [osgi-users] Question on interacting with PROTOTYPE scoped components from an external actor
Hi,
“Typical developer-decision is then to introduce some static setInstance/getInstance methods somewhere where the DS component registers itself when activated.
Which of course only works for singleton components.”
Such a statement really scares me. It shows that the usage of static methods/fields are still quite misunderstood by a lot of people. When developers use it this way, they mostly think static is a way to access an instance from anywhere, but they are missing the thing that all instances of that class will share the same value (as it is on class level, not on the instance). Actually it will create several issues in a multithreaded environment. And I highly recommend to skip such approaches!
If you want to use OSGi services from non-OSGi components, you need to use low-level OSGi mechanisms. Typically by getting the ServiceReference from the BundleContext or better using a ServiceTracker for example.
https://mnlipp.github.io/osgi-getting-started/AccessingAService.html
https://mnlipp.github.io/osgi-getting-started/TrackingAService.html
https://www.knopflerfish.org/osgi_service_tutorial.html#accessing
The BundleContext can be retrieved via
Bundle bundle = FrameworkUtil.getBundle(requestor.getRequestingObjectClass());
BundleContext context = bundle.getBundleContext();
At least if you are running an OSGi framework, otherwise bundle will be null.
Since you need to use low-level OSGi API to retrieve a DS component from a non-OSGi component, the following chapter of the specification should help answering your question:
https://docs.osgi.org/specification/osgi.core/7.0.0/framework.service.html#framework.service.getting
Mit freundlichen Grüßen / Best regards
Dirk Fauth
Cross-Domain Computing Solutions, Cross Automotive Platforms - System, Software and Tools Engineering Engineering Software Methods and Tools1 (XC-ECO/ESM1)
Robert Bosch GmbH | Postfach 30 02 40 | 70442 Stuttgart | GERMANY | www.bosch.com
Tel. +49 711 811-57819 | Telefax +49 711 811 | Dirk.Fauth@xxxxxxxxxxxx
Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000;
Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar Denner,
Prof. Dr. Stefan Asenkerschbaumer, Filiz Albrecht, Dr. Michael Bolle, Dr. Christian Fischer,
Dr. Stefan Hartung, Dr. Markus Heyn, Harald Kröger, Rolf Najork, Uwe Raschke
PROTOTYPE scopes is intended to align with those cases where unique instances are needed, where the instance might keep state and/or be modified (injection in this case) by an external actor along an axis which OSGi does not have insight into or control over (e.g. like DS).
For example, JAX-RS implementations would normally only know the classname of the resource and do a _new_ to get an instance _on demande_ then do some things like injection or proxy and then execute it and then throw away the instance at the end of the request. So the vehicle to protect against that usage in OSGi is to implement the "production" of these instances using PROTOTYPE scope.
- Ray
This touches on a situation we've often encountered before: how to interact with a DS component from something that is not an OSGi component?
Typical developer-decision is then to introduce some static setInstance/getInstance methods somewhere where the DS component registers itself when activated.
Which of course only works for singleton components.
For PROTOTYPE it appears the DS infrastructure is able to understand when a new instance is needed and/or there is some facility somewhere in DS to allow an external actor to ask for a new component creation and get a reference to it to inject/interact with it. Is this the case and if so could you point me to some info about this?
Or do I misunderstand the above and is the only standard approach always to have a consumer component with ReferenceScope.PROTOTYPE_REQUIRED in the @Reference?
Many thanks,
erwin