{"payload":{"allShortcutsEnabled":false,"path":"scr","repo":{"id":242854622,"defaultBranch":"master","name":"felix-dev","ownerLogin":"apache","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2020-02-24T22:09:29.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/47359?v=4","public":true,"private":false,"isOrgOwned":true},"currentUser":null,"refInfo":{"name":"master","listCacheKey":"v0:1709104937.0","canEdit":false,"refType":"branch","currentOid":"f495351917b0d122138cd6ea70d6c4e61f475629"},"tree":{"items":[{"name":"src","path":"scr/src","contentType":"directory"},{"name":"README.md","path":"scr/README.md","contentType":"file"},{"name":"bnd.bnd","path":"scr/bnd.bnd","contentType":"file"},{"name":"changelog.txt","path":"scr/changelog.txt","contentType":"file"},{"name":"obr.xml","path":"scr/obr.xml","contentType":"file"},{"name":"pom.xml","path":"scr/pom.xml","contentType":"file"}],"templateDirectorySuggestionUrl":null,"readme":{"displayName":"README.md","richText":"

Apache Felix Service Component Runtime (SCR)

\n

The Apache Felix Service Component Runtime described by the OSGi Declarative Services Specification is implemented by this bundle. The service component model described by Declarative Services uses a declarative way for publishing, finding and binding to OSGi services

\n

The Java annotations defined by the specification make implementing components easy and reduce the amount of code that needs be written. These annotations are processed at build time and translated into XML descriptor files which in turn are listed in the Service-Component header of the declaring bundle. But the good news is, you usually don't have to worry about this XML, however in case things don't work as expected , it's good to know how these things work.

\n

The Apache Felix Declarative Services implementation is the reference implementation for the OSGi Declarative Services Specification Version 1.4 (R7) and therefore passes the OSGi CT.

\n

Example Usage

\n

To help you get a head start, here is an example of using Declarative Services. As mentioned the used annotations are processed at build time, creating XML descriptor files. These component declarations are read when the declaring bundle is started and the respective components are verified and activated depending on their declaration.

\n

Component

\n

First of all the component must be implemented in a simple Java class. The Declarative Services Specification basically places no restrictions on the contents of this class.

\n

Lets define a very simple class, which implements a java.util.Comparator service:

\n
package sample;\n\nimport java.util.Comparator;\nimport org.osgi.service.component.annotations.Component;\n\n@Component(service = Comparator.class)\npublic class SampleComparator implements Comparator\n{\n    public int compare( Object o1, Object o2 )\n    {\n        // TODO: calculate the result\n        return o1.equals( o2 ) ? 0 : -1;\n    }\n}
\n

This is of course a very simple and not very intelligently implemented comparator...

\n

Activation

\n

It may well be that the component needs to be notified, when it is activated and deactivated. For this, the component may implement an activate method/constructor and a deactivate method. Both methods must be public or protected and can take a variety of parameters.\nHere is the initial class extended with activation and deactivation methods:

\n
package sample;\n\nimport java.util.Comparator;\nimport org.osgi.service.component.annotations.Component;\nimport org.osgi.service.component.annotations.Activate;\nimport org.osgi.service.component.annotations.Deactivate;\n\n@Component(service = Comparator.class)\npublic class SampleComparator implements Comparator\n{\n    public SampleComparator()\n    {\n        // TODO: Do something on activation\n    }\n\n    public int compare( Object o1, Object o2 )\n    {\n        // TODO: calculate the result\n        return o1.equals( o2 ) ? 0 : -1;\n    }\n\n    @Deactivate\n    protected void deactivate()\n    {\n        // TODO: Do something on deactivation\n    }\n}
\n

Service Binding

\n

The next step would probably be to do some service binding. This is somewhat more overhead, as the referenced services must be declared. On the other hand, you do not have to care to listen for these services. As examples of these strategies we will use the event strategy to access an OSGi LogService.

\n

Looking up the Service

\n

To use the service, the reference must be declared by using the @Reference annotation. Here is the respective declaration for a log service to lookup:

\n
private LogService log;\n\n@Reference\nprotected void bindLog(LogService log)\n{\n    this.log = log;\n}\n\nprotected void unbindLog(LogService log)\n{\n    this.log = null;\n}
\n

Or if you want to use field injection, it is just:

\n
@Reference\nprivate LogService log;
\n

You can also use contructor injection:

\n
private final LogService log;\n\n@Activate\npublic Comparator(@Reference LogService logService)\n{\n    this.log = logService;\n}
\n

Apache Maven Support

\n

Both, the maven-bundle-plugin as well as the bnd-maven-plugin supports processing the annotations and creating the XML component descriptors.

\n

Configuration

\n

The Apache Felix Declarative Services implementation can be configured with Framework properties which are read on startup of the implementation bundle and Configuration Admin Service configuration which is provided by the Configuration Admin Service to the service PID org.apache.felix.scr.ScrService.

\n

The following properties are supported:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PropertyDefault ValueDescription
ds.loglevel1Defines a logging level at which messages are logged. This configuration property is converted to an int number used as the OSGi Log Service logging level.
ds.showtracefalsesets the log level to debug if set to true and the ds.loglevel cannot be converted to a value log level
ds.showerrorstrueDisables logging completely if set to false and the ds.loglevel cannot be converted to a value log level and the ds.showtrace is not set to true
ds.factory.enabledfalseEnables Component Factory functionality not compliant with the Declarative Services specification if set to true. Only set this if you really know you need this. See the Non-Standard Component Factory Behaviour section below for more details.
ds.delayed.keepInstancesfalseWhether or not to keep instances of delayed components once they are not referred to any more. The Declarative Services specifications suggests that instances of delayed components are disposed off if there is not used any longer. Setting this flag causes the components to not be disposed off and thus prevent them from being constantly recreated if often used. Examples of such components may be EventHandler services. The default is to dispose off unused components. See FELIX-3039 for details.
\n

The ds.loglevel property is treated as follows:

\n\n

This configuration mechanism is implemented in the ScrConfiguration and its helper classes.

\n

Non-Standard Component Factory Behaviour

\n
\nIf you don't know what this section is about, just ignore it and leave the ds.factory.enabled configuration property unconfigured.\n
\n

This behaviour assumes the component name of the Component Factory component to be Service Factory PID and each configuration with this Service Factory PID causes the service component runtime to actually create and activate an instance of the Component Factory component automatically. This is not foreseen by the specification which defines instantiation of Component Factory components as being purely application controled and not configuration induced.

\n

To have components instantiated with factory configurations, regular components should be used. This case each factory configuration instance will create a component instance.

\n

If you know that you are using Component Factory components depending on this non-standard behaviour you may set the ds.factory.enabled configuration property to true (the default of this property is false thus disabling this functionality for specification compliance).

\n

For details also refer to FELIX-1416

\n

Administration

\n

The OSGi Compendium specification defines an administrative API for Declarative Services through the Service Component Runtime. This bundle implements that service, too.

\n

Based on the runtime api, the Declarative Service Plugin for the Apache Felix Web Console provides support for Declarative Services administration through a browser.

\n

This bundle itself also has a Felix Shell Command providing easy commands to introspect the states of the registered components.

\n

Shell Command

\n

The management API is made available to the Felix Shell as the scr command with a short list of subcommands:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SynopsisDescription
scr help [ <subcommand> ]Show help of the specific <subcommand> or list all known subcommands
scr list [ <bundleId> ]List registered components of the bundle specified by <bundleId> or list all components. Each component is listed with its component ID, the state and the name. <bundleId> man be either the ID of a bundle or the symbolic name of a bundle.
scr info <componentId>Show a complete information dump of the given component. This dump includes the name, status, provided services and information on the service references. <componentId> may be either the ID of a component or the component's name. The component name must be used for disabled components.
scr enable <componentId>Enable the given component if not already enabled. If the component is already destroyed or enabled, this command has no effect. <componentId> may be either the ID of a component or the component's name. The component name must be used for disabled components.
scr disable <componentId>Disable the given component if not already disabled. If the component is already destroyed or disabled, this command has no effect. <componentId> may be either the ID of a component or the component's name. The component name must be used for disabled components.
\n

The administrative API commands are also available in the Gogo shell where the subcommand names must be prefixed with the name space scr. Thus the list command corresponds to scr:list in the Gogo shell.

\n
","errorMessage":null,"headerInfo":{"toc":[{"level":1,"text":"Apache Felix Service Component Runtime (SCR)","anchor":"apache-felix-service-component-runtime-scr","htmlText":"Apache Felix Service Component Runtime (SCR)"},{"level":2,"text":"Example Usage","anchor":"example-usage","htmlText":"Example Usage"},{"level":3,"text":"Component","anchor":"component","htmlText":"Component"},{"level":3,"text":"Activation","anchor":"activation","htmlText":"Activation"},{"level":3,"text":"Service Binding","anchor":"service-binding","htmlText":"Service Binding"},{"level":3,"text":"Looking up the Service","anchor":"looking-up-the-service","htmlText":"Looking up the Service"},{"level":2,"text":"Apache Maven Support","anchor":"apache-maven-support","htmlText":"Apache Maven Support"},{"level":2,"text":"Configuration","anchor":"configuration","htmlText":"Configuration"},{"level":2,"text":"Non-Standard Component Factory Behaviour","anchor":"non-standard-component-factory-behaviour","htmlText":"Non-Standard Component Factory Behaviour"},{"level":2,"text":"Administration","anchor":"administration","htmlText":"Administration"},{"level":3,"text":"Shell Command","anchor":"shell-command","htmlText":"Shell Command"}],"siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fapache%2Ffelix-dev%2Ftree%2Fmaster%2Fscr"}},"totalCount":6,"showBranchInfobar":false},"fileTree":{"":{"items":[{"name":"bundlerepository.osgi-ct","path":"bundlerepository.osgi-ct","contentType":"directory"},{"name":"bundlerepository","path":"bundlerepository","contentType":"directory"},{"name":"cm.json","path":"cm.json","contentType":"directory"},{"name":"configadmin-plugins","path":"configadmin-plugins","contentType":"directory"},{"name":"configadmin","path":"configadmin","contentType":"directory"},{"name":"configurator","path":"configurator","contentType":"directory"},{"name":"connect","path":"connect","contentType":"directory"},{"name":"coordinator","path":"coordinator","contentType":"directory"},{"name":"dependencymanager","path":"dependencymanager","contentType":"directory"},{"name":"doap","path":"doap","contentType":"directory"},{"name":"eventadmin","path":"eventadmin","contentType":"directory"},{"name":"examples","path":"examples","contentType":"directory"},{"name":"features","path":"features","contentType":"directory"},{"name":"fileinstall","path":"fileinstall","contentType":"directory"},{"name":"framework.security","path":"framework.security","contentType":"directory"},{"name":"framework","path":"framework","contentType":"directory"},{"name":"gogo","path":"gogo","contentType":"directory"},{"name":"healthcheck","path":"healthcheck","contentType":"directory"},{"name":"http","path":"http","contentType":"directory"},{"name":"inventory","path":"inventory","contentType":"directory"},{"name":"ipojo","path":"ipojo","contentType":"directory"},{"name":"log.extension","path":"log.extension","contentType":"directory"},{"name":"log","path":"log","contentType":"directory"},{"name":"main.distribution","path":"main.distribution","contentType":"directory"},{"name":"main","path":"main","contentType":"directory"},{"name":"metatype","path":"metatype","contentType":"directory"},{"name":"pom","path":"pom","contentType":"directory"},{"name":"resolver","path":"resolver","contentType":"directory"},{"name":"rootcause","path":"rootcause","contentType":"directory"},{"name":"scr-ext-anno","path":"scr-ext-anno","contentType":"directory"},{"name":"scr","path":"scr","contentType":"directory"},{"name":"systemready","path":"systemready","contentType":"directory"},{"name":"tools","path":"tools","contentType":"directory"},{"name":"utils","path":"utils","contentType":"directory"},{"name":"webconsole-plugins","path":"webconsole-plugins","contentType":"directory"},{"name":"webconsole","path":"webconsole","contentType":"directory"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":"CODE_OF_CONDUCT.md","path":"CODE_OF_CONDUCT.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"check_staged_release.sh","path":"check_staged_release.sh","contentType":"file"},{"name":"stage_existing_artifact.sh","path":"stage_existing_artifact.sh","contentType":"file"}],"totalCount":43}},"fileTreeProcessingTime":13.488647,"foldersToFetch":[],"treeExpanded":true,"symbolsExpanded":false,"csrf_tokens":{"/apache/felix-dev/branches":{"post":"pLu2RKkWANbLkF9GMv4xSlvAxgCHicidZqmmxsAykPh_TFFV6i2JYQiMIbJyxej5g0E-u-Ggk_SzoIdQPGlQJg"},"/apache/felix-dev/branches/fetch_and_merge/master":{"post":"idkce8lLNPQJwJs5PdYvUUaykTTtqxFsISgqq3qrTvgNZRecDhpAcHghz-lbxDmrmNJaReDAe4NG2tTGLZo2fQ"},"/apache/felix-dev/branches/fetch_and_merge/master?discard_changes=true":{"post":"hzv3SdvDfJz3jEWKHPe2gFTvU8czts5_qqkyjsdpB3UDh_yuHJIIGIZtEVp65aB6io-Ytj7dpJDNW8zjkFh_8A"}}},"title":"felix-dev/scr at master ยท apache/felix-dev"}