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