javaosgideclarative-services

Initialization of OSGi prototype components


In OSGi declarative services, I can create prototype instances declaring a ComponentServiceObjects like this:

@Reference(unbind = "-",
           scope=ReferenceScope.PROTOTYPE_REQUIRED)
private ComponentServiceObjects<MyService> serviceProvider;

and then instantiating the service with

service = serviceProvider.getService();

then I can finish the configuration of the instance by setting some other attributes (configuration values or non-OSGi collaborators) with setters. This has the problem, that the activation is performed before the initialization is complete.

Is there a way to inject this attributes before activating the service?

I am using DS in the context of Liferay Portal 7

EDIT

As a clarification I have an example: let's say I have a component DirectoryListener. And I want to initialize several instances of this component, each one with a different directory. I would like to make some initialization during the activation based on this directory.


Solution

  • The consumer of a service does not know anything about the implementing component... or indeed whether the service is implemented by a component at all, versus something more low-level. Therefore it cannot dictate the configuration of the component.

    It sounds like your use-case demands making the directory part of the service API, and therefore your service interface should be DirectoryListenerFactory. The component can be registered as a simple, singleton service and the directory would be passed via a method e.g. createListener(File dir).

    In this scenario you need to be a little careful with lifecycle. If a client calls createListener it should be careful to release that listener when it is no longer needed. For example DirectoryListener could extend java.lang.AutoCloseable.

    Any service dependencies can be injected via @Reference into the component class that implements the factory. I would expect them to be passed to the DirectoryListener instances via constructor.