blob: 5042f03595adf5e7dea58fc2129eff0885e5bd48 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Dependency Manager Lambda :: Apache Felix</title>
<link rel="canonical" href="https://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager/guides/dm-lambda.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" 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&#8217;s new in version 4?</a>
</li>
<li class="nav-item is-current-page" 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&#8217;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="dm-lambda.html">Dependency Manager Lambda</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/dm-lambda.adoc">Edit this Page</a></div>
</div>
<div class="content">
<article class="doc">
<h1 class="page">Dependency Manager Lambda</h1>
<div id="preamble">
<div class="sectionbody">
<hr>
<div class="paragraph">
<p><strong>Welcome to Felix Dependency Manager Lambda.</strong></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_introduction"><a class="anchor" href="#_introduction"></a>Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Since the R8 version, a new dm-lambda library has been introduced in the DM distribution.
This new library allows to programmatically declare OSGi components using a new style based on java8 lambda expressions and other goodies like method references.</p>
</div>
<div class="paragraph">
<p>The new library is based on the <code>builder</code> design pattern applied to java8 lambdas.
Basically, you call a chain of methods from a fluent <code>builder</code>, and at the end of the chain, you call "<code class="code">build()</code>" which returns the actual DM objects that you already know from the original DM API.
We&#8217;ll see later that using lambdas avoids to call the last "<code class="code">build</code>" method and allows to automatically add the constructed DM Component into the DependencyManager object.</p>
</div>
<div class="paragraph">
<p>Please notice that using the dm-lambda library requires the usage of a recent Java8 jvm (the library has been tested with java version "1.8.0_74").</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_comparing_two_activators_using_old_and_new_api"><a class="anchor" href="#_comparing_two_activators_using_old_and_new_api"></a>Comparing two activators using old and new API:</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Before presenting the new API, let&#8217;s get a jump start and dive into a comparison between the old and new API: assume we have a <code>ServiceConsumer</code> which depends on the following services:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a required dependency on <code>ServiceProvider</code> service with a "<code class="code">(p1=v1)</code>" filter.
The dependency is injected in the "<code class="code">ServiceConsumer.setProvider()</code>" method.</p>
</li>
<li>
<p>a Configuration with pid="<code class="code">org.apache.felix.dm.lambda.samples.hello.ServiceConsumer</code>".</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now assume we have <code>ServiceProvider</code> provided with p1="v1" and p2=123 service properties;
and the provider also depends on:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a required <code>LogService</code> service (injected in class fields).</p>
</li>
<li>
<p>a required <code>EventAdmin</code> service (injected in class fields).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Then we have the following typical Activator (we define both components in the same Activator for simplicity):</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.DependencyActivatorBase;
...
public class Activator extends DependencyActivatorBase {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
// Declare our Consumer component
Component consumer = createComponent()
.setImplementation(ServiceConsumer.class)
.add(createServiceDependency().setService(ServiceProvider.class, "(p1=v1)").setRequired(true).setCallbacks("setProvider", null))
.add(createConfigurationDependency().setPid(ServiceConsumer.class.getName()));
dm.add(consumer);
// Declare our ServiceProvider service component
Properties properties = new Properties();
Properties.put("p1", "v1");
properties.put("p2", 123);
Component provider = createComponent()
.setImplementation(ServiceProviderImpl.class)
.setInterface(ServiceProvider.class.getName(), properties)
.add(createServiceDependency().setService(LogService.class).setRequired(true))
.add(createServiceDependency().setService(EventAdmin.class, null).setRequired(true));
dm.add(provider);
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, let&#8217;s rework the above example, using the new dm-lambda API:</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.lambda.DependencyManagerActivator;
...
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
// Declare our Consumer component
component(comp -&gt; comp.impl(ServiceConsumer.class)
.withSvc(ServiceProvider.class, svc -&gt; svc.required().filter("(p1=v1)").add(ServiceConsumer::setProvider))
.withCnf(ServiceConsumer.class.getName()));
// Declare our ServiceProvider service component:
component(comp -&gt; comp.impl(ServiceProviderImpl.class)
.provides(ServiceProvider.class, p1 -&gt; "v1", p2 -&gt; 123)
.withSvc(true, LogService.class, EventAdmin.class));
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_principle"><a class="anchor" href="#_principle"></a>Principle</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The new API is provided by the <code>org.apache.felix.dependencymanager.lambda.jar</code> bundle.
The following builders are currently supported:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>ComponentBuilder: it is used to build org.apache.felix.dm.Component from original DM API.</p>
</li>
<li>
<p>ServiceDependencyBuilder: builds org.apache.felix.dm.ServiceDependency from original DM API.</p>
</li>
<li>
<p>ConfigurationDependencyBuiler: builds org.apache.felix.dm.ConfigurationDependency from original DM API.</p>
</li>
<li>
<p>BundleAdapterBuilder: builds a bundle adapter component from the original DM API.</p>
</li>
<li>
<p>ServiceAdapterBuilder.java: builds a DM service adapter from the original DM API.</p>
</li>
<li>
<p>FactoryPidAdapterBuilder: builds a DM factory pid adapter from the original DM API.</p>
</li>
<li>
<p>FutureDependencyBuilder: it&#8217;s a new feature allowing to "wait for" an asynchronous event represented by a standard jdk8 <code>CompletableFuture</code> object.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>(There is currently no builders for DM ResourceDependency and ResourceAdapter objects, but they will be supported soon).</p>
</div>
<div class="paragraph">
<p>There are two ways to use these builders:</p>
</div>
<div class="paragraph">
<p>You can first instantiate builders using some of the convenient factory methods available from the DependencyManagerActivator class, which is the new base class for dm-lambda activators:</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.lambda.DependencyManagerActivator;
import org.apache.felix.dm.lambda.ComponentBuilder;
import org.apache.felix.dm.Component;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
ComponentBuilder builder = component();
Component comp = builder.impl(Hello.class).build();
dm.add(comp);
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>component()</code> method returns a <code>ComponentBuilder</code> and the call to <code>build</code> at the end of the method calls chain returns the actual DM Component object.</p>
</div>
<div class="paragraph">
<p>Here is a shorter version:</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.lambda.DependencyManagerActivator;
import org.apache.felix.dm.Component;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
Component comp = component().impl(Hello.class).build());
dm.add(comp);
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, most of the time, in an Activator you usually create a Component and immediately add it to the <code>dm</code> object.
So, in order to reduce the code size, you can then use a component() method that accepts a lambda which takes as argument a <code>Consumer&lt;ComponentBuilder&gt;</code> parameter.
So, the lambda has just to invoke the chain of necessary methods from the builder, without having to call the last "<code class="code">build</code>" method.
The constructed Component is then automatically added to the <code>dm</code> object.</p>
</div>
<div class="paragraph">
<p>The following is the same as above, using a <code>consumer&lt;ComponentBuilder&gt;</code> lambda expression:</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.lambda.DependencyManagerActivator;
import org.apache.felix.dm.lambda.ComponentBuilder;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component((ComponentBuilder comp) -&gt; comp.impl(Hello.class));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here is a more concise version where the type of the lambda parameter is not declared:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class));
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_dependency_default_mode_required_or_optional"><a class="anchor" href="#_dependency_default_mode_required_or_optional"></a>Dependency default mode (required or optional ?)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When you declare a dependency without explicitly invoking <code>optional()</code>, <code>required()</code>, or <code>required(boolean)</code>, then by default, the dependency is assumed to be optional.
This is in line with the behavior of the Dependency Manager API.</p>
</div>
<div class="paragraph">
<p>Now, you can change this default behavior by configuring the "<code class="code">org.apache.felix.dependencymanager.lambda.defaultRequiredDependency</code>" system property.
This property can be set with a list of java package prefixes (comma separated).
When a component implementation class starts with one of the package prefixes specified in the above property, then dependencies will be assumed to be required by default.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_adding_service_dependencies_injected_in_class_fields"><a class="anchor" href="#_adding_service_dependencies_injected_in_class_fields"></a>Adding service dependencies injected in class fields.</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can add a dependency using the "<code class="code">withSvc</code>" methods available from the ComponentBuilder interface.
Such methods accept a <code>Consumer&lt;ServiceDependencyBuilder&gt;</code> lambda expression, which may then configure the dependency using a chain of method calls (filter/callbacks,autoconfig, etc &#8230;&#8203;): When you don&#8217;t specify callbacks, services are injected in class fields with compatible service dependency type, but you can specify a field name.
Unavailable optional dependencies are injected as "<code class="code">Null Objects</code>".</p>
</div>
<div class="paragraph">
<p>The following example adds a service dependency on a LogService with a service filter.</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.lambda.DependencyManagerActivator;
import org.apache.felix.dm.lambda.ServiceDependencyBuilder;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class)
.withSvc(LogService.class, (ServiceDependencyBuilder svc) -&gt; svc.filter("(vendor=apache)")));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here is a more concise version where the type of the <code>svc</code> lambda parameter is not declared:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.filter("(vendor=apache)")));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>When injecting services in class fields (auto config mode), there are shotcuts that avoid using a lambda when defining a service dependency.
These shortcuts are available from the ComponentBuilder interface.</p>
</div>
<div class="paragraph">
<p>Examples:</p>
</div>
<h4 id="_declaring_multiple_auto_config_dependencies_in_one_shot_using_varargs_of_interfaces" class="discrete">Declaring multiple auto config dependencies in one shot (using varargs of interfaces):</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withSvc(ConfigurationAdmin.class, EventAdmin.class, MetatypeService.class));</code></pre>
</div>
</div>
<h4 id="_declaring_multiple_auto_config_dependencies_in_one_shot_with_a_required_flag" class="discrete">Declaring multiple auto config dependencies in one shot with a <code>required</code> flag:</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withSvc(true, ConfigurationAdmin.class, EventAdmin.class, MetatypeService.class));</code></pre>
</div>
</div>
<h4 id="_declaring_an_autoconfig_dependency_with_a_required_flag" class="discrete">Declaring an autoconfig dependency with a <code>required</code> flag:</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withSvc(ConfigurationAdmin.class, true));</code></pre>
</div>
</div>
<h4 id="_declaring_an_autoconfig_dependency_with_a_filter_and_required_flag" class="discrete">Declaring an autoconfig dependency with a <code>filter ` and `required</code> flag:</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withSvc(ConfigurationAdmin.class, "(vendor=apache)", true));</code></pre>
</div>
</div>
<h4 id="_declaring_a_autoconfig_dependency_with_a_filter_an_explicit_class_field_and_required_flag" class="discrete">Declaring a autoconfig dependency with a <code>filter `, an explicit class field, and `required</code> flag:</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withSvc(ConfigurationAdmin.class, "(vendor=apache)", "configadmin", true));</code></pre>
</div>
</div>
<div class="paragraph">
<p>Dependency services can be injected in the following kind of fields:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a field having the same type as the dependency.
If the field may be accessed by anythread, then the field should be declared volatile, in order to ensure visibility when the field is auto injected concurrently.</p>
</li>
<li>
<p>a field which is assignable to an <code>Iterable&lt;T&gt;</code> where T must match the dependency type.
In this case, an Iterable will be injected by DependencyManager before the start callback is called.
The Iterable field may then be traversed to inspect the currently available dependency services.
The Iterable can possibly be set to a final value so you can choose the Iterable implementation of your choice (for example, a CopyOnWrite ArrayList, or a ConcurrentLinkedQueue).</p>
</li>
<li>
<p>a <code>Map&lt;K,V&gt;</code> where K must match the dependency type and V must exactly equals Dictionary class.
In this case, a ConcurrentHashMap will be injected by DependencyManager before the start callback is called.
The Map may then be consulted to lookup current available dependency services, including the dependency service properties (the map key holds the dependency services, and the map value holds the dependency service properties).
The Map field may be set to a final value so you can choose a Map of your choice (Typically a ConcurrentHashMap).
A ConcurrentHashMap is "weakly consistent", meaning that when traversing the elements, you may or may not see any concurrent updates made on the map.
So, take care to traverse the map using an iterator on the map entry set, which allows to atomically lookup pairs of Dependency service/Service properties.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_service_dependency_callbacks"><a class="anchor" href="#_service_dependency_callbacks"></a>Service Dependency callbacks</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can specify callbacks on the component implementation class using the "<code class="code">add/change/remove/swap</code>" <code>ServiceDependencyBuilder</code> methods:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.add("setLog")));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now you can also use a more type-safe callback using a Java 8 method reference:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.add(Hello::setLog)));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.add(Hello::setLog).remove(Hello::unsetLog)));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following callback methods signatures are supported when using method references:</p>
</div>
<div class="paragraph">
<p>For add/change/remove method references:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> method(S service)
method(S service, ServiceReference&lt;S&gt; serviceRef),
method(S service, Map&lt;String, Object&gt; serviceProperties)
method(S service, Dictionary&lt;String, Object&gt; serviceProperties)
method(S service, Component serviceComponent)
method(S service, Component serviceComponent, ServiceReference&lt;S&gt; serviceRef)</code></pre>
</div>
</div>
<div class="paragraph">
<p>and for swap method references:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> method(S oldService, S newService)
method(S oldService, S newService, Component component))
method(ServiceReference&lt;S&gt; oldRef, S old, ServiceReference&lt;S&gt; newRef, S newService)
method(ServiceReference&lt;S&gt; oldRef, S old, ServiceReference&lt;S&gt; newRef, S newService, Component component)</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_defining_service_dependency_object_instance_callback"><a class="anchor" href="#_defining_service_dependency_object_instance_callback"></a>Defining Service Dependency Object instance callback</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Sometimes, you want to inject the dependency to a separate object that is not part of the component implementation classes.
For example, the following example injects a dependency in a DependencyHandler instance:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
DependencyHandler depHandler = new DependencyHandler();
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.add(depHandler, "setLog")));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or using method reference:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
DependencyHandler depHandler = new DependencyHandler();
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.add(depHandler::setLog)));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can chain multiple callbacks:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
DependencyHandler depHandler = new DependencyHandler();
component(comp -&gt; comp.impl(Hello.class).withSvc(LogService.class, svc -&gt; svc.add(Hello::setLog).add(depHandler::setLog)));
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_providing_a_service"><a class="anchor" href="#_providing_a_service"></a>Providing a service</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When a component provides a service with some properties, so far it was necessary to create a Dictionary and pass it to the <code>Component.setInterface()</code> method.</p>
</div>
<div class="paragraph">
<p>Now you can pass properties directly to the <code>provides</code> method as varargs of properties (a suite of key-value properties):</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class).provides(HelloService.class, "p1", "v1", "p2", 123));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or if you build your application using the <code>-parameters</code> javac option, you can also use the "<code class="code">FluentProperty</code>" lambda that allows to declare service properties as a suite of &#8220;`+key &#8594; value+`&#8221; lambdas, like this:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Hello.class).provides(HelloService.class, p1 -&gt; "v1", p2 -&gt; 123));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>CAUTION</strong>: defining service properties using lambda parameters only works with Java8 , not Java9/10/11, and this feature may be removed in next version.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_depending_on_a_configuration"><a class="anchor" href="#_depending_on_a_configuration"></a>Depending on a configuration.</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Configuration dependency can be defined using the "<code class="code">withCnf</code>" ComponentBuilder method.
Two families of callbacks are supported:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>reflection based callbacks: you specify a callback method name</p>
</li>
<li>
<p>method reference callbacks: you specify a java8 method reference</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Callbacks may accept a Dictionary, a Component, or a user defined configuration type interface.
If you only specify a pid, by default the callback method name is assumed to be "updated".</p>
</div>
<div class="sect2">
<h3 id="_configuration_types"><a class="anchor" href="#_configuration_types"></a>configuration types</h3>
<div class="paragraph">
<p>Configuration types are a new feature that allows you to specify an interface that is implemented by DM and such interface is then injected to your callback instead of the actual Dictionary.
Using such configuration interface provides a way for creating type-safe configurations from a actual Dictionary that is normally injected by Dependency Manager.
The callback accepts in argument an interface that you have to provide, and DM will inject a proxy that converts method calls from your configuration-type to lookups in the actual map or dictionary.
The results of these lookups are then converted to the expected return type of the invoked configuration method.
As proxies are injected, no implementations of the desired configuration-type are necessary!</p>
</div>
<div class="paragraph">
<p>The lookups performed are based on the name of the method called on the configuration type.
The method names are "mangled" to the following form: [lower case letter] [any valid character]*.
Method names starting with get or is (JavaBean convention) are stripped from these prefixes.
For example: given a dictionary with the key "foo" can be accessed from a configuration-type using the following method names: foo(), getFoo() and isFoo().</p>
</div>
<div class="paragraph">
<p>The return values supported are: primitive types (or their object wrappers), strings, enums, arrays of primitives/strings, Collection types, Map types, Classes and interfaces.
When an interface is returned, it is treated equally to a configuration type, that is, it is returned as a proxy.</p>
</div>
<div class="paragraph">
<p>Arrays can be represented either as comma-separated values, optionally enclosed in square brackets.
For example: [ a, b, c ] and a, b,c are both considered an array of length 3 with the values "a", "b" and "c".
Alternatively, you can append the array index to the key in the dictionary to obtain the same: a dictionary with "arr.0" =&gt; "a", "arr.1" =&gt; "b", "arr.2" =&gt; "c" would result in the same array as the earlier examples.</p>
</div>
<div class="paragraph">
<p>Maps can be represented as single string values similarly as arrays, each value consisting of both the key and value separated by a dot.
Optionally, the value can be enclosed in curly brackets.
Similar to array, you can use the same dot notation using the keys.
For example, a dictionary with</p>
</div>
<div class="paragraph">
<p>"map" =&gt; "{key1.value1, key2.value2}"</p>
</div>
<div class="paragraph">
<p>and a dictionary with</p>
</div>
<div class="paragraph">
<p>"map.key1" =&gt; "value1", "map2.key2" =&gt; "value2"</p>
</div>
<div class="paragraph">
<p>result in the same map being returned.
Instead of a map, you could also define an interface with the methods getKey1() and getKey2 and use that interface as return type instead of a Map.</p>
</div>
<div class="paragraph">
<p>In case a lookup does not yield a value from the underlying map or dictionary, the following rules are applied:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>primitive types yield their default value, as defined by the Java Specification;</p>
</li>
<li>
<p>string, Classes and enum values yield null;</p>
</li>
<li>
<p>for arrays, collections and maps, an empty array/collection/map is returned;</p>
</li>
<li>
<p>for other interface types that are treated as configuration type a null-object is returned.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_multiple_ways_to_define_a_configuration_dependency"><a class="anchor" href="#_multiple_ways_to_define_a_configuration_dependency"></a>multiple ways to define a configuration dependency</h3>
<div class="paragraph">
<p>You can first pass a configuration pid to the <code>withCnf</code> method.
In this example, the Hello component has an "<code class="code">updated(Dictionary properties)</code>" method called when configuration is available or updated.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withCnf("my.pid"))</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can pass a "<code class="code">configuration type</code>" to the <code>withCnf</code> method.
The pid is assumed to be the fqdn of the type passed to the <code>withCnf</code> method, and the callback is assumed to be "<code class="code">updated</code>" and to accept as argument an implementation of the specified configuration type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withCnf(MyConfiguration.class))</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can define the updated callback method explicitly using a ConfigurationDependencyBuilder lambda that you can pass to the "<code class="code">withCnf</code>" method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withCnf((ConfigurationDependencyBuilder cnf) -&gt; cnf.pid("my.pid").update("modified")));</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here is shorter version which does not declare the type of the lambda passed to the <code>withCnf</code> method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withCnf(cnf -&gt; cnf.pid("my.pid").update("modified")));</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also define the callback using a method reference:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Hello.class).withCnf(cnf -&gt; cnf.pid("my.pid").update(Hello::modified)));</code></pre>
</div>
</div>
<div class="paragraph">
<p>And finally, you can define a configuration type, and a callback using a method reference.
Here, the updated callback has to take in argument the configuration type parameter (the pid is assumed to be the fqdn of the configuration type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">component(comp -&gt; comp.impl(Hello.class).withCnf(cnf -&gt; cnf.update(MyConfiguration.class, Hello::modified)));
class Hello {
void modified(MyConfiguration properties) { ... }
}</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="_configuration_dependency_examples_based_on_method_references"><a class="anchor" href="#_configuration_dependency_examples_based_on_method_references"></a>Configuration Dependency Examples based on method references:</h4>
<div class="paragraph">
<p>Code example with a component that defines a Configuration Dependency using a specific callback method reference, and the method accepts in argument a configuration type (the pid is assumed to be the fqdn of the configuration type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public interface MyConfig {
String getAddress();
int getPort();
}
public class ServiceImpl {
void updated(MyConfig cnf) {
if (cnf != null) {
String addr = cnf.getAddress();
int port = cnf.getPort();
...
}
}
}
public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(ServiceImpl.class).withCnf(conf -&gt; conf.update(MyConfig.class, ServiceImpl::updated)));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Same example, using a shortcut for the <code>withCnf</code> dependency, which is only defining the configuration type (the pid is assumed to be the fqdn of the config type, and the callback name is assumed to be "updated"):</p>
</div>
<div class="literalblock">
<div class="content">
<pre>public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(ServiceImpl.class).withCnf(MyConfig.class));
}
}</pre>
</div>
</div>
<div class="paragraph">
<p>Code example with a component that defines a Configuration Dependency using a specific callback method reference which accepts a Dictionary in argument:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp
.impl(ServiceImpl.class)
.withCnf(conf -&gt; conf.pid("my.pid").update(ServiceImpl::setProperties)));
}
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_configuration_dependency_examples_based_on_method_reflection"><a class="anchor" href="#_configuration_dependency_examples_based_on_method_reflection"></a>Configuration Dependency Examples based on method reflection:</h4>
<div class="paragraph">
<p>Code example which defines a configuration dependency injected in the "ServiceImpl.updated(Dictionary)" callback (the pid is directly passed in argument to the <code>withCnf</code> method):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(ServiceImpl.class).withCnf("my.pid")));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Code example with a component that defines a Configuration Dependency using a specific callback method name:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(ServiceImpl.class).withCnf(conf -&gt; conf.pid("my.pid").update("modified")));
}
}</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_managing_components_outside_of_activators"><a class="anchor" href="#_managing_components_outside_of_activators"></a>Managing components outside of Activators.</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can manage Components outside of the Activator by using some static factory methods from the <code>DependencyManagerActivator</code> class.</p>
</div>
<div class="paragraph">
<p>For example, consider a use case where you want to retrieve some information from some already injected services, and you then want to dynamically add more dependencies from your <code>init</code> component callback.
First let&#8217;s look at the Activator:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Pojo.class).withCnf("pojo.pid"));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here, we define a Configuration dependency with a "pojo.pid" configuration pid.
So, now, the Pojo will then for example be able to parse an xml from the configuration, and depending on what it has parsed, it will possibly add more dependencies, like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import static org.apache.felix.dm.lambda.DependencyManagerActivator.*;
import org.apache.felix.dm.Component;
public class Pojo {
void updated(Dictionary conf) throws Exception {
parseXml(conf.get("some.xml.configuration"));
}
void init(Component c) { // lifecycle dm callback that allows you to add more dependencies
if (xmlConfigurationRequiresEventAdmin) {
component(c, comp -&gt; comp.withSvc(EventAdmin.class));
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The available variety of factory methods allows you to also create some DM objects and add them manually, like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import static org.apache.felix.dm.lambda.DependencyManagerActivator.*;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ServiceDependency;
import org.apache.felix.dm.DependencyManager;
public class Pojo {
void updated(Dictionary conf) throws Exception {
parseXml(conf.get("some.xml.configuration"));
}
void init(Component c) { // lifecycle dm callback that allows you to add more dependencies
if (xmlConfigurationRequiresEventAdmin) {
DependencyManager dm = c.getDependencyManager();
ServiceDependency dep = serviceDependency(c, EventAdmin.class).filter("(vendor=felix)").build();
dm.add(dep);
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And an example where you create a new DM component from the code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import static org.apache.felix.dm.lambda.DependencyManagerActivator.*;
import org.apache.felix.dm.DependencyManager;
public class Pojo {
volatile DependencyManager m_dm;
void createComponent() {
component(m_dm, comp -&gt; comp.impl(NewComponent.class).withSvc(LogService.Class, EventAdmin.class));
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_component_lifecycle_callbacks"><a class="anchor" href="#_component_lifecycle_callbacks"></a>Component Lifecycle Callbacks</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Like with DM API, default lifecycle callbacks are the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>"init": the method is called on the component implementation class(es) once all required dependencies declared in the Activator have been injected.
This method can then be used to possibly add more dependencies dynamically.</p>
</li>
<li>
<p>"start": the method is called on the component implementation class(es) once all required dependencies (including the ones added from the "init" callback) have been injected.
Then the optional dependency callbacks are invoked (after the start callback).</p>
</li>
<li>
<p>"stop": the method is called on the component implementation class(es) when some required dependencies are being lost or when the component&#8217;s bundle is stopping.</p>
</li>
<li>
<p>"destroy": the component is destroyed and may be re-created and re-initialized in case some required dependencies comes up again.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You can change the callback names using the "init"/"start"/"stop"/"destroy" methods from the ComponentBuilder interface.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> component(comp -&gt; comp.impl(Pojo.class)
.init("initialize")
.start("activate")
.stop("deactivate")
.destroy("shutdown"));</code></pre>
</div>
</div>
<div class="paragraph">
<p>Same example, but with some specific callback instance on which the callback should be invoked:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>CallbackHandler handler = new CallbackHandler();
component(comp -&gt; comp.impl(Pojo.class)
.init(handler, "initialize")
.start(handler, "activate")
.stop(handler, "deactivate")
.destroy(handler, "shutdown"));</pre>
</div>
</div>
<div class="paragraph">
<p>When using callback instances, you can also use method references using the callback instance object:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>CallbackHandler handler = new CallbackHandler();
component(comp -&gt; comp.impl(Pojo.class)
.init(handler::initialize)
.start(handler::activate)
.stop(handler::deactivate)
.destroy(handler::shutdown));</pre>
</div>
</div>
<div class="paragraph">
<p>Callbacks are empty-args, or may take a DM Component in argument.</p>
</div>
<div class="paragraph">
<p>Method Reference for Component implementations class are not supported.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_aspect_components"><a class="anchor" href="#_creating_aspect_components"></a>Creating Aspect Components</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Like with the original DM API, you can create a chain of aspects (service interceptors) ordered by a ranking attribute, using the "<code class="code">aspect</code>" factory method.
This method accepts in argument a ServiceAspectBuilder.</p>
</div>
<div class="paragraph">
<p>Code example which provides a "LogService" aspect that performs spell-checking of each log message.
The aspect decorates a LogService.
The aspect also depends on a DictionaryService that is internally used to perform log spell checking.
The LogService and DictionaryService services are injected in the aspect implementation using reflection on class fields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
aspect(LogService.class, (ServiceAspectBuilder asp) -&gt; asp.impl(SpellCheckLogAspect.class).rank(10).withSvc(DictionaryService.class));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Same more concise example which does not declare the type of the lambda builder argument:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
aspect(LogService.class, asp -&gt; asp.impl(SpellCheckLogAspect.class).rank(10).withSvc(DictionaryService.class));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Same example, but using callbacks for injecting LogService and DictionaryService in the aspect implementation class:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
aspect(LogService.class, asp -&gt; asp
.impl(SpellCheckLogAspect.class).rank(10)
.add(SpellCheckLogAspect::setLogService)
.withSvc(DictionaryService.class, svc -&gt; svc.add(SpellCheckLogAspect::setDictionary)));
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_service_adapter_components"><a class="anchor" href="#_creating_service_adapter_components"></a>Creating Service Adapter Components</h2>
<div class="sectionbody">
<div class="paragraph">
<p>DM service adapters allow to create adapter services when a given type of adapted service is found in the OSGI registry.
Using the "<code class="code">adapter</code>" factory method, you can pass to it consumer of an <code>ServiceAdapterBuilder</code> that can be used to construct a DM adapter component.</p>
</div>
<div class="paragraph">
<p>Code example that adapts a "Device" service to an HttpServlet service.
The adapter is created using a ServiceAdapterBuilder that is passed to the lambda.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
adapter(Device.class, (ServiceAdapterBuilder adapt) -&gt; adapt.impl(DeviceServlet.class).provides(HttpServlet.class).properties(alias -&gt; "/device");
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Same more concise example which does not declare the type of lambda parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
adapter(Device.class, adapt -&gt; adapt.impl(DeviceServlet.class).provides(HttpServlet.class).properties(alias -&gt; "/device");
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_factory_configuration_adapter_components"><a class="anchor" href="#_creating_factory_configuration_adapter_components"></a>Creating Factory Configuration Adapter Components</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A Factory Configuration Adapter allows to create many instances of the same service, each time a configuration instance is created for a given factory pid.
To declare a factory pid configuration adapter, use the <code>factoryPid</code> method available from the DependencyManagerActivator class and pass to it a lambda for the FactoryPidAdapterBuilder argument:</p>
</div>
<div class="paragraph">
<p>Example that defines a factory configuration adapter service for the "foo.bar" factory pid.
For each factory pid instance, an instance of the DictionaryImpl component will be created:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
factoryPidAdapter((FactoryPidAdapterBuilder adapter) -&gt; adapter
.impl(DictionaryImpl.class).factoryPid("foo.bar").propagate().update(ServiceImpl::updated)
.withSvc(LogService.class, log -&gt; log.optional()));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Same more concise example that is not declaring the type of the lambda type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
factoryPidAdapter(adapter -&gt; adapter
.impl(DictionaryImpl.class).factoryPid("foo.bar").propagate().update(ServiceImpl::updated)
.withSvc(LogService.class, log -&gt; log.optional()));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Example that defines a factory configuration adapter using a user defined configuration type (the pid is by default assumed to match the fqdn of the configuration type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public interface DictionaryConfiguration {
public String getLanguage();
public List&lt;String&gt; getWords();
}
public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
factoryPidAdapter(adapter -&gt; adapter
.impl(DictionaryImpl.class).propagate().update(DictionaryConfiguration.class, ServiceImpl::updated)
.withSvc(LogService.class, log -&gt; log.optional()));
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_a_bundle_adapter_component"><a class="anchor" href="#_creating_a_bundle_adapter_component"></a>Creating a Bundle Adapter component</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A Bundle Adapter is used to create a Component when a bundle that matches a given filter is found.
To build a DM adapter, you can use the "<code class="code">bundleAdapter</code>" factory method: it takes in argument a consumer of a BundleAdapterBuilder object, which is used to construct a real DM BundleAdapter component.</p>
</div>
<div class="paragraph">
<p>Example that creates a BundleAdapter service for each started bundle (the bundle is added using a method reference):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public class Activator extends DependencyManagerActivator {
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
bundleAdapter(adapt -&gt; adapt
.impl(BundleAdapterImpl.class).provides(BundleAdapter.class).mask(Bundle.INSTALLED|Bundle.RESOLVED|Bundle.ACTIVE)
.add(BundleAdapterImpl::bundleStarted)
.withSvc(LogService.class, "(vendor=apache)"));
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_completablefuture_dependency"><a class="anchor" href="#_completablefuture_dependency"></a>CompletableFuture dependency.</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The new library provides a new feature which allows your component to depend on the result of a jdk8 <code>CompletableFuture</code>.
CompletableFuture java8 class provides an asynchronous event-driven model and you can now define dependencies on any asynchronous events, like if they were service dependencies.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s explore this new dependency using an advanced example: assume you develop a component that needs to track any "Tracked" services registered in the Registry, using a classic whiteboard pattern.
But before, you need to download a web page at initialization, before you component is started.
The downloaded webpage is required to be able to handle Tracked services.
Now, you don&#8217;t want to block the initialization of your component because in a reactive word, it is forbidden to block on the current thread.</p>
</div>
<div class="paragraph">
<p>So, you use an <code>HttpClient</code> which allows to asynchronously download a web page: this service is assumed to provide a doGET() method which does not block the current thread, but instead returns <code>CompletableFuture&lt;String&gt;</code> which represents the future result of the asynchronously downloaded page.</p>
</div>
<div class="paragraph">
<p>From your component init() method, you can then declare a FutureDependency on the result of the <code>CompletableFuture&lt;String&gt;</code>.
A Future Dependency can be defined using the "withFuture" method available from the ComponentBuilder interface, and this method takes as argument two args: a CompletableFuture, and a <code>consumer&lt;FutureDependencyBuilder&gt;</code>.
The second arg is a lambda that can be used to configure the callback to invoke when the CF has completed.</p>
</div>
<div class="paragraph">
<p>And once the result completes, start() will be called, and at this point, the Tracked services will then be injected (using DM, optional service callbacks are always invoked after the start() callback, never before).</p>
</div>
<div class="paragraph">
<p>So, the Activator looks like this:</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.lambda.DependencyManagerActivator;
public class Activator extends DependencyManagerActivator {
@Override
public void init(BundleContext ctx, DependencyManager dm) throws Exception {
component(comp -&gt; comp.impl(Pojo.class).provides(PojoService)
.withCnf(cnf -&gt; cnf.pid("foo.pid"))
.withSvc(HttpClient.class, svc -&gt; svc.required())
.withSvc(Tracked.class, svc -&gt; svc.optional().add(Pojo::bindTracked));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, here is the implementation for our component which downloads the URL from its init method.
The init method will declare a "FutureDependency" for the result of the <code>CompletableFuture&lt;String&gt;</code> returned by the HttpClient.
And once the result is injected in the setPage callback, then the start() callback will be called, and finally, any registered Tracked services will be injected in the "bindTracked" method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import static org.apache.felix.dm.lambda.DependencyManagerActivator.*;
import org.apache.felix.dm.Component;
public class Pojo implements PojoService {
HttpClient m_httpClient; // injected.
String m_url; // the URL to download using the http client.
void updated(Dictionary&lt;String, Object conf) throws Exception {
m_url = (String) conf.get("download.url");
}
// lifecycle dm callback that allows you to add more dependencies. start will be called once the webpage has been downloaded.
void init(Component c) {
// Let's schedule a download for our web page.
CompletableFuture&lt;String&gt; futurePage = m_httpClient.doGET(m_url);
// Add a required dependency to the result of the CF, and inject the result in our setPage method.
component(c, comp -&gt; comp.withFuture(futurePage, future -&gt; future.complete(this::setPage)));
}
void setPage(String content) {
// Called when the CompletableFuture has completed
}
void start() {
// We have downloaded the page, our component is starting and is about to be registered
}
void bindTracked(Tracked service) {
// a Tracked service is injected, we can handle it because we are fully initialized.
// (optional service callbacks are always invoked after the start callback).
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>So, using the Future Dependency we can nicely reuse the jdk CompletableFuture as a required dependency.
Without using the FutureDependency on the CompletableFuture returned by the HttpClient, we would then have to manually register our service using bundleContext.registerService (once the web page has been downloaded), and we would then have to check if the webpage has been downloaded each time a Tracked service is injected.
And in case the page is not available, we would then have to cache the injected Tracked service and process it later, once the page has been downloaded.</p>
</div>
<div class="paragraph">
<p>Also, notice that when the page is injected in the setPage() method, you absolutely don&#8217;t need to deal with synchronization at all because in DM, all lifecycle and dependency callbacks are safely scheduled in a "serial queue" associated to the component.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_sample_codes"><a class="anchor" href="#_sample_codes"></a>Sample codes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>many samples codes are available from the distribution source release: Please take a look at the following:</p>
</div>
<div class="sect2">
<h3 id="_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasampleshello"><a class="anchor" href="#_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasampleshello"></a>org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/</h3>
<div class="paragraph">
<p>This sample provides a DM Activator declaring one service consumer and a service provider.
The ServiceConsumer is also depending on a configuration pid (see org.apache.felix.dependencymanager.samples.hello.Configurator).</p>
</div>
</div>
<div class="sect2">
<h3 id="_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplescompositefactory"><a class="anchor" href="#_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplescompositefactory"></a>org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/</h3>
<div class="paragraph">
<p>This Activator is an example usage of DM composite components.
A composite component is implemented using a composition of multiple object instances, which are used to implement a given service.</p>
</div>
<div class="paragraph">
<p>The sample also uses a Factory approach in order to instantiate the composition of objects: A "CompositionManager" is first injected with a Configuration that can possibly be used to create and configure all the composites.</p>
</div>
<div class="paragraph">
<p>Dependencies are injected to some of the component implementation instances, using java8 method references.
For instance, the LogService is only injected in the ProviderImpl and the ProviderComposite1 class and not in the ProviderComposite2 class.</p>
</div>
</div>
<div class="sect2">
<h3 id="_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesdevice"><a class="anchor" href="#_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesdevice"></a>org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/</h3>
<div class="paragraph">
<p>This is an example showing a Dependency Manager "Adapter" in action.
Two kinds of services are registered in the registry: some Device, and some DeviceParameter services.
For each Device (having a given id), there is also a corresponding "DeviceParameter" service, having the same id.</p>
</div>
<div class="paragraph">
<p>Then a "DeviceAccessImpl" adapter service is defined: it is used to "adapt" the "Device" service to a "DeviceAccess" service, which provides the union of each pair of Device/DeviceParameter having the same device.id . The adapter also dynamically propagate the service properties of the adapted Device service.</p>
</div>
</div>
<div class="sect2">
<h3 id="_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesdictionary"><a class="anchor" href="#_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesdictionary"></a>org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/</h3>
<div class="paragraph">
<p>This sample shows a "SpellChecker" application which provides a "dictionary:spellcheck" GOGO shell command.
The GOGO "dictionary:spellcheck" command accepts a string as parameter, which is checked for proper exactness.
The SpellChecker class has a required/multiple (1..N) dependency over every available "DictionaryService" services, which are internally used by the SpellChecker command, when checking word exactness.</p>
</div>
<div class="paragraph">
<p>A DictionaryService is defined using a FactoryConfigurationAdapterService , allowing to instantiate many "DictionaryService" instances for each configuration that are added to the factory pid "Spell Checker Configuration" from web console.
The factory pid configuration metatypes are defined using the bnd "metatype" annotations (see DictionaryConfiguration.java).</p>
</div>
<div class="paragraph">
<p>The DictionaryService is decorated with a DictionaryAspect, which you can instantiate by adding a configuration to the "Spell Checker Aspect Dictionary" pid from web console.
The aspect configuration metatype is also declared using the bnd metatype annotations (see DictionaryAspectConfiguration.java).</p>
</div>
<div class="paragraph">
<p>Before running this sample, go to webconsole, and add some words in the "<code class="code">Spell Checker Configuration</code>" factory PID, and in the "<code class="code">Spell Checker Aspect Dictionary</code>" PID.</p>
</div>
<div class="paragraph">
<p>Then go to gogo shell, and type dm help.
You will normally see the dictionary:spellcheck command.
Type dictionary:spellcheck with some words configured either in the spell checker configuration, or in the spell checker aspect configuration, and the dictionary will check for proper word exactness.</p>
</div>
</div>
<div class="sect2">
<h3 id="_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesfactory"><a class="anchor" href="#_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesfactory"></a>org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/</h3>
<div class="paragraph">
<p>This sample is an example usage of DM components that are created using a Factory object.
The Factory is defined using java8 method references.</p>
</div>
</div>
<div class="sect2">
<h3 id="_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesfuture"><a class="anchor" href="#_org_apache_felix_dependencymanager_lambda_samplessrcorgapachefelixdmlambdasamplesfuture"></a>org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/</h3>
<div class="paragraph">
<p>The purpose of this sample is to show an example usage of the new "CompletableFuture" dependency that has been added in the dm-lambda library.
CompletableFuture java8 class provides functional operations and promotes an asynchronous event-driven model.</p>
</div>
<div class="paragraph">
<p>In such model, you can use the new dm-lambda library to add dependencies on asynchronous events using the standard JDK CompletableFuture class.</p>
</div>
<div class="paragraph">
<p>In this example, the Activator first defines a PageLink component that is used to download a given page from the web.
The service then parses the content of the page and returns all available hrefs (links) found from the web page.</p>
</div>
<div class="paragraph">
<p>The PageLink is initialized with the Felix web site URL, which is asynchronously downloaded from the PageLink::init method, using a CompletableFuture.
The CF is then added as a "FutureDependency" in the PageLinkImpl.init() method, and when the CF completes, the PageLinkImpl.start() callback is invoked and the service is registered.</p>
</div>
<div class="paragraph">
<p>The Activator is then getting injected with the PageLink service, and displays the links (hrefs) found from the Felix web site.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
if you are using a corporate http proxy, you have to fix the Activator in order to configure the ip addr and port number of your http proxy.
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_javadoc"><a class="anchor" href="#_javadoc"></a>Javadoc</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can find the javadoc for the new Dependency Manager Lambda library <a href="../../../../apidocs/">here</a>.</p>
</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>