| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <title>Dependency Manager - Annotations :: Apache Felix</title> |
| <link rel="canonical" href="https://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager/guides/annotations.html"> |
| <meta name="generator" content="Antora 2.3.4"> |
| <link rel="stylesheet" href="../../../../_/css/site.css"> |
| <link rel="icon" href="../../../../_/img/favicon.png" type="image/x-icon"> |
| </head> |
| <body class="article"> |
| <header class="header"> |
| <nav class="navbar"> |
| <div class="navbar-brand"> |
| <a class="navbar-item" href="https://felix.apache.org/index.html"> |
| <span> |
| <img src="../../../../_/img/logo.png"> |
| </span> |
| </a> |
| <button class="navbar-burger" data-target="topbar-nav"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </button> |
| </div> |
| <div id="topbar-nav" class="navbar-menu"> |
| <div class="navbar-end"> |
| <a class="navbar-item" href="https://felix.apache.org/index.html">Home</a> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Subprojects</a> |
| <div class="navbar-dropdown"> |
| <a class="navbar-item" href="../../apache-felix-dependency-manager.html">Dependency Manager</a> |
| <a class="navbar-item" href="../../apache-felix-event-admin.html">Event Admin</a> |
| <a class="navbar-item" href="../../apache-felix-file-install.html">File Install</a> |
| <a class="navbar-item" href="../../apache-felix-framework.html">Framework</a> |
| <a class="navbar-item" href="../../apache-felix-gogo.html">Gogo Shell</a> |
| <a class="navbar-item" href="../../apache-felix-healthchecks.html">Health Checks</a> |
| <a class="navbar-item" href="../../apache-felix-inventory.html">Inventory</a> |
| <a class="navbar-item" href="../../apache-felix-log.html">Log</a> |
| <a class="navbar-item" href="../../apache-felix-logback.html">Logback</a> |
| <a class="navbar-item" href="../../apache-felix-maven-bundle-plugin.html">Maven bundle plugin</a> |
| <a class="navbar-item" href="../../apache-felix-maven-scr-plugin.html">Maven SCR plugin</a> |
| <a class="navbar-item" href="../../apache-felix-metatype-service.html">Metatype Service</a> |
| <a class="navbar-item" href="../../apache-felix-preferences-service.html">Preferences Service</a> |
| <a class="navbar-item" href="../../apache-felix-remote-shell.html">Remote Shell</a> |
| <a class="navbar-item" href="../../apache-felix-script-console-plugin.html">Script console plugin</a> |
| <a class="navbar-item" href="../../apache-felix-shell.html">Lightweight shell</a> |
| <a class="navbar-item" href="../../apache-felix-shell-tui.html">Shell TUI</a> |
| <a class="navbar-item" href="../../apache-felix-web-console.html">Web Console</a> |
| </div> |
| </div> |
| <div class="navbar-item"> |
| <span class="control"> |
| <a class="button is-primary" href="../../../downloads.html">Downloads</a> |
| </span> |
| </div> |
| </div> |
| </div> |
| </nav> |
| </header> |
| <div class="body"> |
| <div class="nav-container" data-component="documentation" data-version="master"> |
| <aside class="nav"> |
| <div class="panels"> |
| <div class="nav-panel-menu is-active" data-panel="menu"> |
| <nav class="nav-menu"> |
| <h3 class="title"><a href="../../../index.html">Documentation</a></h3> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="0"> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../../../documentation.html">Documentation</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../../../downloads.html">Downloads</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../../../getting-started.html">Getting Started</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../../../news.html">News</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Community</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../community/project-info.html">Apache Felix Project Info</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../community/contributing.html">Contributing</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../community/projects-using-felix.html">Projects Using Felix</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Development</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../development/coding-standards.html">Coding Standards</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../development/dependencies-file-template.html">DEPENDENCIES file template</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../development/provisional-osgi-api-policy.html">Provisional OSGi API Policy</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../development/release-management-nexus.html">Release Management</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../development/site-how-to.html">Site How To</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../development/using-the-osgi-compliance-tests.html">Using the OSGi Compliance Tests</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../faqs.html">FAQS</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../faqs/apache-felix-bundle-plugin-faq.html">Apache Felix Bundle Plugin Frequently Asked Questions</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../faqs/apache-felix-scr-plugin-faq.html">Apache Felix SCR Plugin Frequently Asked Questions</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../subprojects.html">Subprojects</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../apache-felix-dependency-manager.html">Apache Felix Dependency Manager</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Guides</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="migrating-from-earlier-versions.html">Apache Felix Dependency Manager - Migrating from earlier versions</a> |
| </li> |
| <li class="nav-item is-current-page" data-depth="4"> |
| <a class="nav-link" href="annotations.html">Dependency Manager - Annotations</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="background.html">Dependency Manager - Background</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="bundles-and-dependencies.html">Dependency Manager - Bundles and Dependencies</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="design-patterns.html">Dependency Manager - Design Patterns</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="development.html">Dependency Manager - Development</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="history.html">Dependency Manager - History</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="javadocs.html">Dependency Manager - JavaDocs</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="migrating-from-other-solutions.html">Dependency Manager - Migrating from other solutions.</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="performance-tuning.html">Dependency Manager - Performance Tuning</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="resources.html">Dependency Manager - Resource adapters</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="whatsnew.html">Dependency Manager - What’s new in version 4?</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="dm-lambda.html">Dependency Manager Lambda</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="whatsnew-r15.html">What’s New in R15</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Reference</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/component-adapter.html">Dependency Manager - Adapter</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/component-aspect.html">Dependency Manager - Aspect</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/component-bundle-adapter.html">Dependency Manager - Bundle Adapter</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/dependency-bundle.html">Dependency Manager - Bundle Dependency</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/components.html">Dependency Manager - Components</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/dependency-configuration.html">Dependency Manager - Configuration Dependency</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/dependencies.html">Dependency Manager - Dependencies</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/external-links.html">Dependency Manager - External Links</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/component-factory-configuration-adapter.html">Dependency Manager - Factory Configuration Adapter Service</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/component-resource-adapter.html">Dependency Manager - Resource Adapter</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/dependency-resource.html">Dependency Manager - Resource Dependency</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/dependency-service.html">Dependency Manager - Service Dependency</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/service-scopes.html">Dependency Manager - Service Scopes</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/component-singleton.html">Dependency Manager - Singleton Component</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/thread-model.html">Dependency Manager - Thread Model</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../reference/dm-annotations.html">Dependency Manager Annotations</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Tutorials</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../tutorials/working-with-annotations.html">Dependency Manager - Annotations</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../tutorials/getting-started.html">Dependency Manager - Getting Started</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../tutorials/leveraging-the-shell.html">Dependency Manager - Leveraging the shell</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../tutorials/sample-code.html">Dependency Manager sample projects</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-event-admin.html">Apache Felix Event Admin</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-file-install.html">Apache Felix File Install</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../apache-felix-framework.html">Apache Felix Framework</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-framework/apache-felix-framework-bundle-cache.html">Apache Felix Framework Bundle Cache</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-framework/apache-felix-framework-configuration-properties.html">Apache Felix Framework Configuration Properties</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-framework/apache-felix-framework-faq.html">Apache Felix Framework Frequently Asked Questions</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-framework/apache-felix-framework-launching-and-embedding.html">Apache Felix Framework Launching and Embedding</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-framework/apache-felix-framework-usage-documentation.html">Apache Felix Framework Usage Documentation</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-framework-security.html">Apache Felix Framework Security</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../apache-felix-gogo.html">Apache Felix Gogo</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-gogo/rfc-147-overview.html">RFC 147 Overview</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-healthchecks.html">Apache Felix Health Checks</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-inventory.html">Apache Felix Inventory Printer</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-log.html">Apache Felix Log</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-logback.html">Apache Felix Logback</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-maven-bundle-plugin-bnd.html">Apache Felix Maven Bundle Plugin (BND)</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-metatype-service.html">Apache Felix Metatype Service</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-osgi-bundle-repository.html">Apache Felix OSGi Bundle Repository (OBR)</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-preferences-service.html">Apache Felix Preferences Service</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-remote-shell.html">Apache Felix Remote Shell</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-shell.html">Apache Felix Shell</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../apache-felix-shell-tui.html">Apache Felix Shell TUI</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../apache-felix-web-console.html">Apache Felix Web Console</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-web-console/extending-the-apache-felix-web-console.html">Extending the Apache Felix Web Console</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-web-console/web-console-restful-api.html">Web Console RESTful API</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-web-console/web-console-security-provider.html">Web Console Security Provider</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Extensions</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../../apache-felix-web-console/extending-the-apache-felix-web-console/branding-the-web-console.html">Branding the Web Console</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../../apache-felix-web-console/extending-the-apache-felix-web-console/providing-resources.html">Providing Resources</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../../apache-felix-web-console/extending-the-apache-felix-web-console/providing-web-console-plugins.html">Providing Web Console Plugins</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../../apache-felix-web-console/extending-the-apache-felix-web-console/web-console-logging.html">Web Console Logging</a> |
| </li> |
| <li class="nav-item" data-depth="4"> |
| <a class="nav-link" href="../../apache-felix-web-console/extending-the-apache-felix-web-console/web-console-output-templating.html">Web Console Output Templating</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Maven SCR plugin</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-maven-scr-plugin/apache-felix-maven-scr-plugin-use.html">Apache Felix Maven SCR Plugin Use</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-maven-scr-plugin/apache-felix-scr-bndtools-use.html">Apache Felix SCR Annotations BndTools Use</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-maven-scr-plugin/apache-felix-scr-ant-task-use.html">Apache Felix SCR Ant Task Use</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-maven-scr-plugin/extending-scr-annotations.html">Extending SCR Annotations Excerpt: How add new Annotations extending the base Annotations</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-maven-scr-plugin/scr-annotations.html">SCR Annotations Excerpt: Using Java 5 Annotations to describe the component or service.</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../apache-felix-maven-scr-plugin/scr-javadoc-tags.html">SCR JavaDoc Tags Excerpt: Using JavaDoc Tags to describe the component or service.</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations.html">Tutorials</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-application-demonstration.html">Apache Felix Application Demonstration</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial.html">Apache Felix OSGi Tutorial</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-faq.html">OSGi Frequently Asked Questions</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">OSGI Tutorial</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-1.html">Apache Felix Tutorial Example 1 - Service Event Listener Bundle</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-2.html">Apache Felix Tutorial Example 2</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-2b.html">Apache Felix Tutorial Example 2b</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-3.html">Apache Felix Tutorial Example 3</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-4.html">Apache Felix Tutorial Example 4</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-5.html">Apache Felix Tutorial Example 5</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-6.html">Example 6 - Spell Checker Service Bundle</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-7.html">Example 7 - Spell Checker Client Bundle</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-8.html">Example 8 - Spell Checker Service using Service Binder</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-9.html">Example 9 - Spell Checker Service using Declarative Services</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../../../license.html">Apache License 2.0</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../../../site-map.html">Site map</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </nav> |
| </div> |
| <div class="nav-panel-explore" data-panel="explore"> |
| <div class="context"> |
| <span class="title">Documentation</span> |
| <span class="version">master</span> |
| </div> |
| <ul class="components"> |
| <li class="component is-current"> |
| <span class="title">Documentation</span> |
| <ul class="versions"> |
| <li class="version is-current is-latest"> |
| <a href="../../../index.html">master</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </aside> |
| </div> |
| <main class="article"> |
| <div class="toolbar" role="navigation"> |
| <button class="nav-toggle"></button> |
| <a href="../../../index.html" class="home-link"></a> |
| <nav class="breadcrumbs" aria-label="breadcrumbs"> |
| <ul> |
| <li><a href="../../../index.html">Documentation</a></li> |
| <li><a href="../../../subprojects.html">Subprojects</a></li> |
| <li><a href="../../apache-felix-dependency-manager.html">Apache Felix Dependency Manager</a></li> |
| <li>Guides</li> |
| <li><a href="annotations.html">Dependency Manager - Annotations</a></li> |
| </ul> |
| </nav> |
| <div class="edit-this-page"><a href="https://github.com/apache/felix-antora-site/edit/main/modules/ROOT/pages/subprojects/apache-felix-dependency-manager/guides/annotations.adoc">Edit this Page</a></div> |
| </div> |
| <div class="content"> |
| <article class="doc"> |
| <h1 class="page">Dependency Manager - Annotations</h1> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This section presents a quick overview of the capabilities and usage of the DependencyManager Java annotations. |
| In particular, we will recap the DependencyManager annotation architecture, and identify some simple usage scenarios using a SpellChecker sample application with annotated components. |
| The application is available from the felix trunk, in the <code>dependencymanager/samples.annotation</code> subproject.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_architecture"><a class="anchor" href="#_architecture"></a>Architecture</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Instead of writing Activators which extends the DependencyActivatorBase class, service components can now be annotated using the annotations provided by the <em>org.apache.felix.dependencymanager.annotation</em> bundle. |
| Annotations are not reflectively parsed at runtime; |
| but we use a BND plugin which scans annotations at compilation phase and generates a compact metadata file in the bundle’s META-INF/dependencymanager subdirectory. |
| This has the following benefits:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>JVM startup speed is not affected, and class files are not parsed when the framework is starting</p> |
| </li> |
| <li> |
| <p>Moreover, since the annotations are not retained by the VM at runtime, it is not necessary to load the annotation API bundle at runtime.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>At runtime, the metadata generated during the compilation phase are processed by a specific DependencyManager Runtime bundle, which is in charge of managing the service component lifecycle and dependencies. |
| This Runtime bundle actually uses the DependencyManager programmatic API in order to manage the annotated components. |
| Annotated components can then be inspected with the DependencyManager Gogo shell, as it is the case with DM components declared through the programmatic DM API.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_registering_a_service"><a class="anchor" href="#_registering_a_service"></a>Registering a Service</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>To register a service, your can annotate your class with a <em>@Component</em> annotation, and an instance of your class will be registered under all directly implemented interfaces into the OSGi registry. |
| You can however take control on the interfaces to be exposed, and in this case, you can use the <em>provides</em> attribute, which takes a list of classes to expose from the registry.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To illustrate this, we are now introducing a SpellChecker application which provides a Felix "spellcheck" Gogo shell command. |
| Gogo is the new shell supported by the Felix Framework. |
| Our "spellcheck" command is implemented by the SpellChecker component which accepts a string as parameter. |
| This string is then checked for proper existence. |
| To do the checking, The SpellChecker class has a required/multiple (1..N) dependency over every available DictionaryService services. |
| Such DictionaryService represents a real dictionary for a given language (it has a <em>lang</em> service property), and is configurable/instantiable from the OSGi Configuration Admin Service.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Configuration Admin service provides a mechanism for configuring components (using ManagedService interfaces), and WebConsole actually implements this service. |
| ConfigAdmin is also able to instantiate some Services (using ManagedServiceFactory interfaces).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Now we have introduced the background, here is the SpellCheck component:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Component(provides={SpellChecker.class}, |
| properties={@Property(name=CommandProcessor.COMMAND_SCOPE, value="dmsample.annotation"), |
| @Property(name=CommandProcessor.COMMAND_FUNCTION, values={"spellcheck"})}) |
| public class SpellChecker { |
| // --- Gogo Shell command |
| |
| @Descriptor("checks if word is found from an available dictionary") |
| public void spellcheck(@Descriptor("the word to check")String word) { |
| // Check the proper existence of the word parameter, using injected DictionaryService instances |
| // ... |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In the code above, you see that the SpellCheck is annotated with the <em>@Component</em> annotation. |
| Gogo runtime does not required shell commands to implement a specific interface. |
| Commands just have to register some Pojos in the OSGi registry, but the only thing required is to provide the Pojos with two service properties ( COMMAND_SCOPE, and COMMAND_FUNCTION) which will be used by the Gogo runtime when instropecting the Pojo for invoking the proper functions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>So, coming back to the sample code, the SpellChecker class registers itself into the OSGi registry, using the <em>provides</em> attribute, which just refer to our SpellChecker class, and the two mandatory Gogo service properties are also specified using the <em>@Property</em> annotation. |
| It is not shown here, but service properties can also be provided dynamically from a method that can return a Map, and annotated with the <em>@Start</em> lifecycle callback, but we will see this feature in a another section.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_depending_on_a_service"><a class="anchor" href="#_depending_on_a_service"></a>Depending on a Service</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Our SpellChecker component can expose itself as a Gogo shell command, but before being registered into the OSGi registry, we also need to be injected with two dependencies: one required dependency (at minimum) on a DictionaryService, and another optional one on a LogService. |
| First, let’s look at the DictionaryService, which is a simple interface:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public interface DictionaryService { |
| /** |
| * Check for the existence of a word. |
| * @param word the word to be checked. |
| * @return true if the word is in the dictionary, false otherwise. |
| */ |
| public boolean checkWord(String word); |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>And here is our previous SpellChecker component, augmented with two new ServiceDependency annotations:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Component(provides={SpellChecker.class}, |
| properties={@Property(name=CommandProcessor.COMMAND_SCOPE, value="dmsample.annotation"), |
| @Property(name=CommandProcessor.COMMAND_FUNCTION, values={"spellcheck"})}) |
| public class SpellChecker { |
| @ServiceDependency(required = false) |
| private LogService m_log; |
| |
| private CopyOnWriteArrayList<DictionaryService> m_dictionaries = new CopyOnWriteArrayList<DictionaryService>(); |
| |
| @ServiceDependency(removed = "removeDictionary") |
| protected void addDictionary(DictionaryService dictionary) { |
| m_dictionaries.add(dictionary); |
| } |
| |
| protected void removeDictionary(DictionaryService dictionary) { |
| m_dictionaries.remove(dictionary); |
| } |
| |
| // --- Gogo Shell command |
| |
| @Descriptor("checks if word is found from an available dictionary") |
| public void spellcheck(@Descriptor("the word to check")String word) { |
| m_log.log(LogService.LOG_INFO, "Checking spelling of word \"" + word |
| + "\" using the following dictionaries: " + m_dictionaries); |
| |
| for (DictionaryService dictionary : m_dictionaries) { |
| if (dictionary.checkWord(word)) { |
| System.out.println("word " + word + " is correct"); |
| return; |
| } |
| } |
| System.err.println("word " + word + " is incorrect"); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>There are many things to describe in the code above:</p> |
| </div> |
| <div class="paragraph"> |
| <p>First, we define an optional dependency on the LogService, by defining a <em>@ServiceDependency(required=false)</em> annotation on our m_logService field: This means that our component will be provided into the OSGi registry even if there is no available LogService, and in this case, a NullObject will be injected in our class field; |
| This will avoid to check for nullability, when using the m_logService field. |
| All optional dependencies applied on class fields are injected with a NullObject (when not available). |
| The NullObject can be invoked and will do nothing. |
| For a lot of cases that is good enough to handle optional dependencies. |
| But when you really want to check if an optional service is there or not, then you have to apply the optional dependency on a callback method, which will be called when the optional service is available.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Next comes the dependency on the DictionaryService. |
| Here, we use a <em>ServiceDependency</em> annotation, but this time we apply it on a method (<em>add/removeDictionary</em>). |
| There is no need to specify the "<em>required=true</em>" flag because it is the default value. |
| Notice that this behavior is different from the API, where service dependencies are optional by default . We use a callback method, because we just need to register all available DictionaryService services in our dictionary list, which is used when checking word existence. |
| This list is a copy on write list because the dependency may be injected at any time, possibly from another thread. |
| So, using a copy on write list avoid us to use synchronized methods.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_creating_a_service_from_configadmin"><a class="anchor" href="#_creating_a_service_from_configadmin"></a>Creating a Service from ConfigAdmin</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The <em>@Component</em> annotation is not the only one for creating services. |
| Another one is the <em>@FactoryConfigurationAdapterService</em> annotation which allows to instantiate many instances of the same annotated service class from ConfigAdmin (and WebConsole). |
| To illustrate this, let’s take a look at our DictionaryImpl class which is part of the SpellChecker sample. |
| This service is required by the SpellChecker component, when checking for proper word existence. |
| And you can instantiate as many DictionaryService as you want, from ConfigAdmin …​</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@FactoryConfigurationAdapterService(factoryPid="DictionaryImplFactoryPid", updated="updated") |
| public class DictionaryImpl implements DictionaryService { |
| /** |
| * We store all configured words in a thread-safe data structure, because ConfigAdmin |
| * may invoke our updated method at any time. |
| */ |
| private final CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>(); |
| |
| /** |
| * Our Dictionary language. |
| */ |
| private String m_lang; |
| |
| /** |
| * Our service will be initialized from ConfigAdmin, and we also handle updates in this method. |
| * @param config The configuration where we'll lookup our words list (key="words"). |
| */ |
| protected void updated(Dictionary<String, ?> config) { |
| m_lang = (String) config.get("lang"); |
| m_words.clear(); |
| String[] words = (String[]) config.get("words"); |
| for (String word : words) { |
| m_words.add(word); |
| } |
| } |
| |
| /** |
| * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole. |
| */ |
| public boolean checkWord(String word) { |
| return m_words.contains(word); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Our DictionaryImpl class implements a DictionaryService, and our class will be registered under that interface (all directly implemented interfaces are used when registering the service, but you can select some others using the <em>provides</em> attribute). |
| The <em>@FactoryConfigurationAdapterService</em> annotation will instantiate our service for each configuration created from web console (and matching our "DictionaryImplFactoryPid" factoryPid).</p> |
| </div> |
| <div class="paragraph"> |
| <p>We also use the <em>updated</em> attribute, which specifies a callback method which will handle properties configured by ConfigAdmin. |
| The updated callback will also be called when our properties are changing. |
| Every properties are propagated to our service properties, unless the properties starting with a dot ("."). |
| Configuration properties starting with a dot (".") are considered private and are not propagated.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Notice that you can mix standard bnd metatype annotations with DM annotations, in order describe configurations meta data (default values, property labels, etc …​ |
| see <a href="http://bnd.bndtools.org/chapters/210-metatype.html" class="bare">http://bnd.bndtools.org/chapters/210-metatype.html</a>). |
| So, let’s revisit our DisctionaryImpl service, but this time with meta type support:</p> |
| </div> |
| <div class="paragraph"> |
| <p>First, we define an interface for describing our configuration metadata, with bnd metatype annotations:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import java.util.List; |
| |
| import aQute.bnd.annotation.metatype.Meta.AD; |
| import aQute.bnd.annotation.metatype.Meta.OCD; |
| |
| @OCD(name="Spell Checker Dictionary (annotation)", factory = true, description = "Declare here some Dictionary instances") |
| public interface DictionaryConfiguration { |
| @AD(description = "Describes the dictionary language", deflt = "en") |
| String lang(); |
| |
| @AD(description = "Declare here the list of words supported by this dictionary. This properties starts with a Dot and won't be propagated with Dictionary OSGi service properties") |
| List<String> words(); |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Next, here is our DictionaryImpl that will use the bnd "Configurable" helper in order to retrieve the actual configuration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.apache.felix.dm.annotation.api.FactoryConfigurationAdapterService; |
| import org.apache.felix.dm.annotation.api.ServiceDependency; |
| import org.apache.felix.dm.annotation.api.Start; |
| import org.osgi.service.log.LogService; |
| import aQute.bnd.annotation.metatype.Configurable; |
| |
| @FactoryConfigurationAdapterService(factoryPidClass = DictionaryConfiguration.class, propagate = true, updated = "updated") |
| public class DictionaryImpl implements DictionaryService { |
| private final CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>(); |
| private String m_lang; |
| |
| protected void updated(Dictionary<String, ?> config) { |
| if (config != null) { |
| // use bnd "Configurable" helper to get an implementation for our DictionaryConfiguration. |
| DictionaryConfiguration cnf = |
| Configurable.createConfigurable(DictionaryConfiguration.class, config); |
| |
| m_lang = cnf.lang(); |
| m_words.clear(); |
| for (String word : cnf.words()) { |
| m_words.add(word); |
| } |
| } |
| } |
| |
| public boolean checkWord(String word) { |
| return m_words.contains(word); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_providing_an_aspect"><a class="anchor" href="#_providing_an_aspect"></a>Providing an Aspect</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>As we have seen in the previous section, there are many annotations that can be used to specify a service. |
| Another one is the <em>@AspectService</em> annotation. |
| This annotation allows to <em>decorate</em> an existing service in order to add certain "capabilities" to it, like adding a specific caching mechanism to a storage service or implementing logging. |
| Aspects can be plugged to an existing service at runtime, and can also be removed dynamically. |
| This is transparent, and the clients using the existing service are not interrupted, they are just rebound with the aspect service.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As an example, we go back to our SpellChecker application, and we are now looking at the DictionaryAspect class. |
| This class uses the <em>@Aspect</em> Service annotation in order to add some custom words to an English DictionaryService (with the service property lang=en). |
| The Extra words to add to the English Dictionary will be configured from ConfigAdmin. |
| That’s why the class also uses a <em>@ConfigurationDependency</em> annotation:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@AspectService(ranking = 10, filter = "(lang=en)") |
| public class DictionaryAspect implements DictionaryService { |
| /** |
| * This is the service this aspect is applying to. |
| */ |
| private volatile DictionaryService m_originalDictionary; |
| |
| /** |
| * We store all configured words in a thread-safe data structure, because ConfigAdmin may |
| * invoke our updated method at any time. |
| */ |
| private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>(); |
| |
| /** |
| * Defines a configuration dependency for retrieving our english custom words (by default, |
| * our PID is our full class name). |
| */ |
| @ConfigurationDependency |
| protected void updated(Dictionary<String, ?> config) { |
| m_words.clear(); |
| String[] words = (String[]) config.get("words"); |
| for (String word : words) { |
| m_words.add(word); |
| } |
| } |
| |
| /** |
| * Checks if a word is found from our custom word list. if not, delegate to the decorated |
| * dictionary. |
| */ |
| public boolean checkWord(String word) { |
| if (m_words.contains(word)) { |
| return true; |
| } |
| return m_originalDictionary.checkWord(word); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The annotation does the following: because our class implements the DictionaryService contract, it will instantiate our service each time it finds another existing DictionaryService matching the filter attribute we provide in the annotation (filter="(lang=en)"). |
| And it will inject the existing service in our m_originalDictionary field, by reflection. |
| But we can also specify a field attribute in the annotation, if we want to explicitly inject the existing service in a given class field. |
| So, any client depending on an English DictionaryService will be transparently rebound to our aspect Dictionary.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the Annotation, also notice the <em>ranking</em> attribute: It is the level used to organize the aspect chain ordering (multiple aspects may be applied on a given service).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>ConfigurationDependency</em> is another dependency that we have not seen before: it is used to configure the extra English words from ConfigAdmin. |
| This annotation normally requires a pid parameter, which is a persistent identifier uniquely identifying our component, but by default, the pid is set to the fully qualified name of our class.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_how_to_run_the_sample_code"><a class="anchor" href="#_how_to_run_the_sample_code"></a>How to run the sample code</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Just import the Dependency source distribution in bndtools and check the following samples:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/annot/README</p> |
| </li> |
| <li> |
| <p>org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/api/README</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </article> |
| <aside class="toc sidebar" data-title="Contents" data-levels="2"> |
| <div class="toc-menu"></div> |
| </aside> |
| </div> |
| </main> |
| </div> |
| <footer class="footer"> |
| <p>Content licensed under AL2. UI licensed under MPL-2.0 with extensions licensed under AL2</p> |
| </footer> |
| <script src="../../../../_/js/site.js"></script> |
| <script async src="../../../../_/js/vendor/highlight.js"></script> |
| </body> |
| </html> |