1
votes

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.

2
Can you clarify please? You want to call some methods on the service before the component's initialization completes? That is impossible... the guarantee offered by DS is that the component will be fully initialized before any service consumer can invoke any method on it. - Neil Bartlett
BTW the unbind="-" attribute on @Reference does nothing and should be removed. - Neil Bartlett
Thank you for the remark about unbind! I was using it in my code because I saw it in a lot of other places, but I had the impression that it was useless. - AdrianRM
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. If it is not possible, I will have to use another method which runs after the activation. Or is there a better approach? - AdrianRM
No this isn't possible, the client of a component does not get to dictate the configuration of that component. It sounds like you want to register a DirectoryListenerFactory instead. - Neil Bartlett

2 Answers

2
votes

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.

0
votes

Neil Bartlett:

No this isn't possible, the client of a component does not get to dictate the configuration of that component. It sounds like you want to register a DirectoryListenerFactory instead.