Search code examples
javaosgiblueprint-osgi

Get an OSGi service instance from blueprint programmatically


I have a java class where I need to have full control the time and place of instantiation - therefore I can't initialize it as blueprint bean.

In the same bundle as that class I have a bean that I export as an OSGi-service. I would need to get access to that very service instance from the previously explained non-blueprint class.

I can't just perform a service lookup as there are other services implementing the same interface aswell. Creating a second (internal) instance of the service class will not work either.

So, as a recap:

  • Before I used blueprint, I had the service implementation as classic singleton, enabling me to register the same instance as service in the activator class that I could later access from within the bundle. But with blueprint (as far as I know) making the service class a "classic" singleton is not possible because it would not be possible for blueprint to create the service instance
  • I can't perform a service lookup because there is more than one service registered implementing the service interface.

My current solution is to query all services implementing the interface and looping the list to find the one thats instance of the one class I want.

BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
ServiceReference<?>[] refs = ctx.getServiceReferences(ServiceInterface.class.getName(), null);
ServiceImpl provider = null;
for (ServiceReference ref : refs) {
    if (ctx.getService(ref) instanceof ServiceImpl) {
        provider = (ServiceImpl) ctx.getService(ref);
    }
}

But I do not really like the idea of that approach.

Is there any better way to solve that? Maybe some way to request a service instance direct from the blueprint container? I found the interface BlueprintContainer with a method to get instances by the ID they got - but again the only way to get an instance of the BlueprintContainer I found is to inject the instance in the class - where I hit the initial problem of the class not possible to be a blueprint bean again.


Solution

  • Just set a property when exporting the service. So you can filter for it. This way you can distinguish your service impl from the others.

    I also propose to use a ServiceTracker for your service. So you do not have to handle the lookup for every call to the service. If you do not use a ServiceTracker make sure to unget the service after use.