You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2018/10/09 23:09:14 UTC

svn commit: r1843364 - /felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext

Author: pderop
Date: Tue Oct  9 23:09:14 2018
New Revision: 1843364

URL: http://svn.apache.org/viewvc?rev=1843364&view=rev
Log:
dm r12 updates.

Added:
    felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext   (with props)

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext?rev=1843364&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext Tue Oct  9 23:09:14 2018
@@ -0,0 +1,217 @@
+Title:
+Notice:    Licensed to the Apache Software Foundation (ASF) under one
+           or more contributor license agreements.  See the NOTICE file
+           distributed with this work for additional information
+           regarding copyright ownership.  The ASF licenses this file
+           to you under the Apache License, Version 2.0 (the
+           "License"); you may not use this file except in compliance
+           with the License.  You may obtain a copy of the License at
+           .
+             http://www.apache.org/licenses/LICENSE-2.0
+           .
+           Unless required by applicable law or agreed to in writing,
+           software distributed under the License is distributed on an
+           "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+           KIND, either express or implied.  See the License for the
+           specific language governing permissions and limitations
+           under the License.
+
+Title: Dependency Manager - Service Scopes
+
+By default service providers are registered once in the osgi registry, and all service consumers share the same service provider instance.
+Now, you can control the scope of the provided services: From the provider side, a "scope" parameter 
+is available for all types of DM components and allows to define the scope of the registered service.
+
+The `scope` attribute has three enum values: SINGLETON, BUNDLE, PROTOTYPE
+
+- SINGLETON: it's as before: your registered service is a singleton, meaning that the service must be 
+instantiated and registered once, and all using services will share the same service instance of your component.
+- BUNDLE: the service will be registered as a ServiceFactory, meaning an instance of the component must be 
+created for each bundle using the service.
+- PROTOTYPE: the service will be registered as a PrototypeServiceFactory, meaning the service is registered as 
+a prototype scope service and an instance of the component must be created for each distinct service requester.
+
+Scoped Services are supported by all kind of DM service components:
+
+- Component
+- Aspects
+- Adapters
+- Bundle Adapters
+- Resource Adapters
+
+When a consumer requests a service (using ServiceDependency), then DM will automatically 
+dereference the service like this:
+
+- if the service has a SERVICE_SCOPE service property matching SCOPE_PROTOTYPE, the DM will 
+internally derefence the service using the ServiceObject API: so, the consumer will get its own copy 
+of the requested service instance.
+- else, DM will internally dereference the service, as before.
+When defining scoped component implementation, you can optionally define two special class fields 
+in order to get injected with the client Bundle requesting the service, and the ServiceRegisgtration 
+Object. Just use @Inject annotations in order to get injected with the client 
+Bundle or the ServiceRegistration. You can also define a constructor which takes as argument the 
+client bundle as well as the service registration.
+
+# Examples
+
+So, here is a MyService component with PROTOTYPE scope, and each requester will get its own copy 
+of MyService instance (the MyServiceImpl.start() method will be called for each MyServiceImpl 
+instance):
+
+    :::java
+    public class Activator extends DependencyActivatorBase {
+        @Override
+        public void init(BundleContext context, DependencyManager dm) throws Exception {
+            dm.add(createComponent()
+                .setScope(ServiceScope.PROTOTYPE)
+                .setInterface(MyService.class.getName(), null)
+                .setImplementation(MyServiceImpl.class));
+        }
+    }
+    
+    public class MyServiceImpl implements MyService {
+        void start() {
+            // called on each MyService instance
+        }
+    }
+
+The MyServiceImpl, like with annotations, can define a constructor in order to be injected with 
+the client bundle invoking the service and also the service Registration:
+
+    :::java
+    public class MyServiceImpl implements MyService {
+        public MyServiceImpl(Bundle clientBundle, ServiceRegistration reg) { ... }
+        void start() {
+            // called on each MyService instance
+        }
+    }
+
+(if you want to auto configure the client Bundle, and the ServiceRegistration, then simply define class fields, they will be auto injected, unless you disable auto configuraiton for Bundle/ServiceRegistration using Component.setAutoConfig(Class, boolean) methods.
+
+Here is a Client component which simply depends on the MyService service using a basic DM 
+activator (nothing special to do):
+
+    :::java
+    public class Activator extends DependencyActivatorBase {
+        @Override
+        public void init(BundleContext context, DependencyManager dm) throws Exception {
+            dm.add(createComponent()
+                .setImplementation(Client.class)
+                .add(createServiceDependency()
+                     .setService(MyService.class, null).setRequired(true).setCallbacks("bind", "unbind"));
+        }
+    }
+    
+    public class Client {
+        void bind(MyService service) {
+            // our client is injected with a specific instance of the MyService component 
+            // that is created for our Client.
+            // If another component defines a service dependency on MyService, then the other 
+            // component will get its own private copy of MyService component instance
+        }
+    }
+
+# Example using ServiceObjects API
+
+If now you want to control the creation of the MyService using raw OSGI ServiceObjects API, 
+you can also do it like this:
+
+
+    :::java
+    public class Client {
+        void bind(ServiceObjects<MyService> so) {
+            MyService s1 = so.getService();
+            MyService s2 = so.getService();
+            ...
+            so.ungetService(s1); // will deactivate the MyService s1 instance
+            so.ungetService(s2); // will deactivate the MyService s2 instance
+        }
+    }
+
+# Scoped services and init/destroy callbacks
+
+When you need to specify dynamic dependencies from your component.init() method, 
+the following mechanism will be used:
+
+first, if your component defines an init callback, then one single component prototype instance singleton is created, as if the component is declared with SCOPE=SINGLETON.
+so, the prototype instance will be invoked in the init callback, but won't be started or stopped
+and when all dependencies are satisfied (including the dynamic dependencies), 
+then the ServiceFactory (or PrototypeServiceFactory) is registered.
+And when one client will request a component instance, then a clone will be created and returned.
+
+Example of a scoped component which defines an init method:
+
+    :::java
+    import org.apache.felix.dm.annotation.api.Component;
+    import org.apache.felix.dm.annotation.api.ServiceScope;
+    
+    @Component(scope=ServiceScope.PROTOTYPE)
+    public static class MyServiceImpl implements MyService {
+       
+       @Init
+       void init(Component comp) {
+            // add dependencies dynamically
+       }
+    
+        @Start
+    	void start() {
+    	   // only called on clones, not on the prototype instance
+    	}
+    	
+    	@Stop
+    	void stop() {
+    	   // called on each clone, not on the prototype instance singleton
+    	}
+    }
+
+# Limitation when using DM ServiceDependency from API and ServiceObjects
+
+When using DependencyManager ServiceDependency from the native API (not using annotations), 
+you have to know that the ServiceDependency always internally dereferences and creates the 
+scoped service, even if you specify a ServiceObjecs 
+parameter in your bind method. If now you really want to disable the auto-deref ServiceDependency 
+(because you want to directly use the ServiceObjects API), you must then use the 
+"setDereference(false") method on your ServiceDependency: in this way, you tell DM to never 
+dereference internally the scoped service. Here is an example:
+
+    :::java
+    public class Activator extends DependencyActivatorBase {
+        @Override
+        public void init(BundleContext context, DependencyManager dm) throws Exception {
+            dm.add(createComponent()
+                .setImplementation(Client.class)
+                .add(createServiceDependency()
+                     .setService(MyService.class, null).setRequired(true).setCallbacks("bind", "unbind")
+                     .setDereference(false));
+        }
+    }
+    
+    public class Client {
+        void bind(ServiceObjects<MyService> so) {
+            MyService s1 = so.getService();
+            MyService s2 = so.getService();
+            ...
+            so.ungetService(s1); // will deactivate the MyService s1 instance
+            so.ungetService(s2); // will deactivate the MyService s2 instance
+        }
+    }
+
+In the above example, the Activator defines the ServiceDependency using the 
+ServiceDependency.setDereference(false) method because it's the Client.bind method which will 
+create the MyService instances manually.
+
+In the future, I will try to auto detect the signatures of the Client.bind method in order to 
+never auto-dereference the injected service in case the bind method takes as argument a 
+ServiceObjects (or a ServiceReference) method.
+
+
+
+
+
+
+
+
+
+
+
+

Propchange: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/service-scopes.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native