That's one more attempt to make a dig at the theme "there is no order of OSGI bundles activation".
I have 4 services (bundles) which implement the same interface DataProvider
meaning they implement it literally and also have it as service = { DataProvider.class }
at their @Component
annotations. This interface provides something like diagnostic data from these services. I want to collect this data from all 4 services and to print it on the GUI, which is also an OSGI bundle in my big framework. In order to do that I created such a reference in my GUI bundle:
@Reference
private volatile List<DataProvider> dataProvider;
and then I want to iterate over that list and append to the GUI's textframe everything I need.
The problem is that at the moment when GUI bundle starts, only two of four services are activated, so my list will contain only two service objects instead of all four and print only them. The last two services are loaded after my GUI Bundle has been already activated, because they also wait until their own references become fully satisfied (where some network operations are done, so it takes some time, around 10 seconds). Of course I want my GUI to show the diagnostic data from all 4 services. What could I do for that?
I tried to add policyOption = ReferencePolicyOption.GREEDY
to the @Reference
annotation, I expected it would force to reactivate GUI bundle each time this List<DataProvider> dataProvider
receives a new member, but no, it didn't happen.
P.S. yes there is certainly a straightforward solution: just to add Thread.sleep()
to the GUI Bundle with some appropriate value, so to the time of awakening the discussed above list will be full. But this is really bad thing, I don't want the user waits like 10 seconds before GUI appears, not to speak about the situations, when something goes wrong.
You can specify the minimum cardinality in the configuration. In your case, this is specified with the dataProvider.minimum.cardinality
property in the configuration for your component. (See section 112.6.2.2 Minimum Cardinality Property.)
package com.example;
@Component
public class Diagnostics {
@Reference
List<DataProvider> dataProvider;
}
So then you need to add a configuration record for PID com.example.Diagnostics
:
dataProvider.minimum.cardinality = 4
This model of using configuration works very well with the Configurator Specification. With this specification, you can specify the configuration of an application in a bundle.
Alternatively, you can create 4 references and distinguish the services by a property, using the target
annotation method to specify a filter.