You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Pierre De Rop (JIRA)" <ji...@apache.org> on 2016/12/09 23:45:59 UTC

[jira] [Commented] (FELIX-5336) Add support for prototype scope services in DM4

    [ https://issues.apache.org/jira/browse/FELIX-5336?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15736700#comment-15736700 ] 

Pierre De Rop commented on FELIX-5336:
--------------------------------------

Hi Jan Willem,

I have something working. can you please try it ?
I have attached to this issue FELIX-5336.tgz (it's not a diff, but a tar.tgz of the modified/added files).

so, to install, first checkout dm from the trunk, then cd to dependencymanager , and tar zxvf FELIX-5336.tgz
(the tar.gz contains some more fix for other issues , I will create more JIRA issues soon about them).

now, in the org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/servicescope/api/, there is a demo.

I'm now describing the model used (a bit different from the one initially described in this issue).

So, to create a scoped service component, you can now invoke the createComponent(ComponentPolicy) method.
The policy is an enum allowing to define a strategy about how components are created.
you can also use the policy for all adapters, and for aspects.

this enum contains the following (it is actually only used when the component is a service provider):

- ComponentPolicy.SINGLETON: -> singleton component, as usual.
- ComponentPolicy.BUNDLE -> an instance of the component must be created for each bundle using the service. it actually corresponds to a ServiceFactory
- ComponentPolicy.BUNDLE_DYNAMIC: same as ComponentPolicy.BUNDLE, but allows to define a component which can add some dynamic dependencies from its init/start callback.
- ComponentPolicy.PROTOTYPE -> an instance of the component must be created for each distinct request for the service. it actually corresponds to a PrototypeServiceFactory
- ComponentPolicy.PROTOTYPE_DYNAMIC: same as ComponentPolicy.BUNDLE, but allows to define a component which can add some dynamic dependencies from its init/start callback.


So, for BUNDLE, and PROTOTYPE, a hidden component will track dependencies, and will register a ServiceFactory, or a PrototypeServiceFactory, respectively. 

when a component instance is created (because there is a requester for the service), then the component will be injected with the bundle / service registration (if it defines a Bundle or a ServiceRegistration field). This parameters correspond to the ones passed to the actual Service ServiceFactory.getService (or PrototypeServiceFactory.getService) methods.

So, if your scoped service provider component is dynamic (it may add some dynamic dependencies from the init or start callback), then you can use one of the two
constants from the enum:

BUNDLE_DYNAMIC, or PROTOTYPE_DYNAMIC.

In this case, a prototype instance component is always created (singleton), it will then be called as a regular DM component, and will add any dynamic dependencies it is necessary to add from the init or start callbacks. And once fully started (all required + instance bound dependencies injected), then the corresponding ServiceFactory or PrototypeServiceFactory will then be registered. And when a requester will define a dependency on the service, a copy of the prototype component instance will be created and returned by the ServiceFactory.getService (or PrototypeServiceFactory.getService) methods. Notice that the prototype component instance (singleton) won't be injected with the "Bundle" or "ServiceRegistration" parameters. This will allow you to detect if your component is the prototype instance or if it's a clone being created and returned to the requesting service.

In the demo (see org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/servicescope/api/), you have a Provider which is a prototype scope service: it does not add some dynamic dependencies from its init/start callbacks. So, there is now two Client instances which get injected with their own copy of the ProviderImpl.

You also have a DynamicProvider: it is a scoped service (PROTOTYPE_DYNAMIC), and the prototype instance is first created in order to add a dynamic dependency from the init method.
and once started, then the corresponding PrototypeServiceFactory will be registered.

At this point, a ConsumerUsingServiceObjects component will be started, and in this example, unlike from the Client example, A ServiceReference to the DynamicProvider is injected. I did not have time to inject a ServiceObjects directly. So for now, if you need to manually create some instances, you have to use the ref in order to get the ServiceObjects. Then from the ConsumerUsingServiceObjects.start() method, two instances of the DynamicProvider component  are created, and deleted from the stop() method.

one important remark: when you are using ServiceReference, by default the Component for the ConsumerUsingServiceObjects  will aquire an instance of the DynamicProvider.
for the moment, I don't have added some complexity in the state machine in order to detect that you actually only need to get injected with a ServiceReference (and not with the service itself). So, in order to avoid having a DynamicProvider automatically dereferenced by the ConsumerUsingServiceObjects Component (internally), you will see in the demo Activator that I have introduced  a new "dereference(boolean)" method in the ServiceDependency interface: it allows you to tell to DM that you don't want your component to automatically dereference the injected service internally, because all you want is the just the ServiceReference, not the actual service. So, please for now, use the dereference(boolean) method. (see the Activator in the demo).

Please tell me what you think about all this, and I can then possibly make a release soon.
thanks a lot.

> Add support for prototype scope services in DM4
> -----------------------------------------------
>
>                 Key: FELIX-5336
>                 URL: https://issues.apache.org/jira/browse/FELIX-5336
>             Project: Felix
>          Issue Type: New Feature
>          Components: Dependency Manager
>    Affects Versions: org.apache.felix.dependencymanager-r8
>            Reporter: Pierre De Rop
>            Assignee: Pierre De Rop
>             Fix For: org.apache.felix.dependencymanager-r9
>
>         Attachments: PrototypeServiceFactoryTest.java
>
>
> In the users mailing list, there is a wish to add support in DM4 for OSGi prototype scope services, which allows any service consumer to get its own instance of a given service dependency.
> See http://www.mail-archive.com/users@felix.apache.org/msg17473.html



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)