blob: f5ea679a99df21cf975899f44a4629034e24e28b [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Dependency Manager / Apache Celix</title>
<link rel="icon" href="/assets/img/favicon.ico">
<link href="/assets/css/bootstrap.min.css" rel="stylesheet">
<link href="/assets/css/style.css" rel="stylesheet">
<style>
.card-body img {
max-width: 100%;
width: 100%;
height: auto;
}
.card-body img + em {
text-decoration: underline;
}
</style>
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '9']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
</head>
<body class="light-grey">
<a href="https://github.com/apache/celix" class="github-ribbon">
<img src="/assets/img/forkme_right_red_aa0000.png" alt="Fork me on GitHub">
</a>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top">
<div class="container">
<a class="navbar-brand" href="/">
<img src="/assets/img/celix-white.svg" height="40" class="d-inline-block align-top" alt="Celix Logo">
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/download.cgi">Download</a>
</li>
<li class="nav-item dropdown active">
<a class="nav-link dropdown-toggle" href="#" id="ddDocs" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Docs
</a>
<div class="dropdown-menu" aria-labelledby="ddDocs">
<a class="dropdown-item" href="/docs/2.4.0/docs.html">2.4.0 (latest)</a>
<a class="dropdown-item" href="/docs/2.3.0/docs.html">2.3.0</a>
<a class="dropdown-item" href="/docs/2.2.1/docs.html">2.2.1</a>
<a class="dropdown-item" href="/docs/2.1.0/docs.html">2.1.0</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="ddContributing" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Contributing
</a>
<div class="dropdown-menu" aria-labelledby="ddContributing">
<a class="dropdown-item" href="/contributing/youatcelix.html">You at Celix</a>
<a class="dropdown-item" href="/contributing/submitting-patches.html">Submitting patches</a>
<a class="dropdown-item" href="/contributing/source-and-builds.html">Source code and builds</a>
<hr>
<a class="dropdown-item" href="/contributing/releasing.html">Releasing</a>
<a class="dropdown-item" href="/contributing/volunteers.html">Volunteers</a>
<a class="dropdown-item" href="https://whimsy.apache.org/board/minutes/Celix.html">Board Reports</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="ddSupport" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Support
</a>
<div class="dropdown-menu" aria-labelledby="ddSupport">
<a class="dropdown-item" href="/support/mailing-list.html">Mailing Lists</a>
<a class="dropdown-item" href="/support/issue-tracking.html">Issue Tracking</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="ddFoundation" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
ASF
</a>
<div class="dropdown-menu" aria-labelledby="ddFoundation">
<a class="dropdown-item" href="https://www.apache.org/">ASF Home</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/how-it-works.html">How it works</a>
<a class="dropdown-item" href="https://www.apache.org/licenses/">License</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a>
<a class="dropdown-item" href="https://www.apache.org/security/">Security</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<div class="section">
<div class="container">
<div class="row py-4">
<div class="col-sm-12 card">
<div class="card-body pt-5">
<a href="/docs/2.1.0/docs.html" title="back to documentation">&lt;&lt; back to documentation</a>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<h1 id="apache-celix-dependency-manager">Apache Celix Dependency Manager</h1>
<h2 id="introduction">Introduction</h2>
<p>The Dependency Manager contains a static library which can be used to manage (dynamic) services on a higher abstraction level in a declarative style.
The Apache Celix Dependency Manager is inspired by the <a href="http://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager.html">Apache Felix Dependency Manager</a>.</p>
<h2 id="components">Components</h2>
<p>Components are the main building blocks for OSGi applications. They can publish services, and/or they can have dependencies. These dependencies will influence their life cycle as component will only be activated when all required dependencies are available.</p>
<p>Within Apache Celix a component is expected to have a set of functions where the first argument is a handle to the component (e.g. self/this). How this is achieved is up the the user, for some examples how this can be done see the example in the Apache Celix Project.</p>
<p>The Dependency Manager, as part of a bundle, shares the generic bundle life cycle explained in the OSGi specification.
Each component you define gets its own life cycle. The component life cycle is depicted in the state diagram below.</p>
<p><img src="doc-images/statediagram.png" alt="Component Life Cycle"></p>
<p>Changes in the state of the component will trigger the following life cycle callback functions:</p>
<pre><code>`init`,
`start`,
`stop` and
`deinit`.
</code></pre>
<p>The callback functions can be specified by using the component_setCallbacks.</p>
<h2 id="dm-parts">DM Parts</h2>
<p>The Dependency Manager consist out of four main parts: <code>DM (Dependency Manager) Activator</code>, <code>Dependency Manager</code>, <code>DM Component</code> and <code>DM Service Dependency</code>.</p>
<h3 id="dm-activator">DM Activator</h3>
<p>The <code>DM Activator</code> implements a &ldquo;normal&rdquo; Celix bundle activator and depends on four functions which needs to be implemented by the user of the Depedency Manager:</p>
<ul>
<li><code>dm_create</code> : Should be used to allocated and initialize a dm activator structure. If needed this structure can be used to store object during the lifecycle of the bundle.</li>
<li><code>dm_init</code> : Should be used to interact with the <code>Dependency Manager</code>. Here a user can components, service dependencies and provided services.</li>
<li><code>dm_destroy</code> : Should be used to deinitialize and deallocate objects created in the <code>dm_create</code> function.</li>
</ul>
<h3 id="dependency-manager">Dependency Manager</h3>
<p>The <code>Dependency Manager</code> act as an entry point to add or remove DM Components. The <code>Dependency Manager</code> is provided to the <code>dm_init</code> functoin.</p>
<h3 id="dm-component">DM Component</h3>
<p>The <code>DM Component</code> manages the life cycle of a component. For example, when all required service dependencies are available the <code>DM Component</code> will call the <code>start</code> specified callback function of the component.</p>
<p>The <code>component_setImplementation</code> function can be used to specify which component handle to use.
The <code>component_addInterface</code> can be used to specify one additional service provided by the component.
The <code>component_addServiceDependency</code> can be used to specify one additional service dependency.</p>
<h3 id="dm-service-dependency">Dm Service Dependency</h3>
<p>The <code>DM Service Dependency</code> can be used to specify service dependencies for a component. i</p>
<p>When these dependencies are set to required the <code>DM Component</code> will ensure that components will only be started when all required dependencies are available and stop the component if any of the required dependencies are removed.
This feature should prevent a lot of boiler plating code compared to using a service tracker or services references directly.</p>
<p>A service dependency update strategy can also be specified. Default this strategy is set to <code>DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND</code> this strategy will stop and start (suspend) a component when any of the specified service dependencies change (are removed, added or modified).
When correctly used this strategy removes the need for locking services during updates/invocation. See the dependency manager example for more details.</p>
<p>The <code>serviceDependency_setCallbacks</code> function can be used to specify the function callback used when services are added, set, removed or modified.
The <code>serviceDependency_setRequired</code> function can be used to specify if a service dependency is required.
The <code>serviceDependency_setStrategy</code> function can be used to specify a service dependency update strategy (suspend or locking).</p>
<h3 id="snippets">Snippets</h3>
<h4 id="dm-bundle-activator">DM Bundle Activator</h4>
<p>The next snippet shows a dm bundle activator and how to add components to the dependency manager.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic">//exmpl_activator.c
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span><span style="color:#080">#include</span> <span style="color:#080">&lt;dm_activator.h&gt;</span><span style="color:#080">
</span></span></span><span style="display:flex;"><span><span style="color:#080">#include</span> <span style="color:#080">&lt;stdlib.h&gt;</span><span style="color:#080">
</span></span></span><span style="display:flex;"><span><span style="color:#080"></span>
</span></span><span style="display:flex;"><span><span style="color:#a2f;font-weight:bold">struct</span> dm_exmpl_activator {
</span></span><span style="display:flex;"><span> <span style="color:#0b0;font-weight:bold">exmpl_t</span><span style="color:#666">*</span> exmpl;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#0b0;font-weight:bold">celix_status_t</span> <span style="color:#00a000">dm_create</span>(bundle_context_pt context, <span style="color:#0b0;font-weight:bold">void</span> <span style="color:#666">**</span>userData) {
</span></span><span style="display:flex;"><span> <span style="color:#666">*</span>userData <span style="color:#666">=</span> <span style="color:#00a000">calloc</span>(<span style="color:#666">1</span>, <span style="color:#a2f;font-weight:bold">sizeof</span>(<span style="color:#a2f;font-weight:bold">struct</span> dm_exmpl_activator));
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">return</span> <span style="color:#666">*</span>userData <span style="color:#666">!=</span> <span style="color:#a2f">NULL</span> <span style="color:#666">?</span> <span style="color:#a0a000">CELIX_SUCCESS</span> : CELIX_ENOMEM;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#0b0;font-weight:bold">celix_status_t</span> <span style="color:#00a000">dm_init</span>(<span style="color:#0b0;font-weight:bold">void</span> <span style="color:#666">*</span> userData, bundle_context_pt context, dm_dependency_manager_pt manager) {
</span></span><span style="display:flex;"><span> <span style="color:#0b0;font-weight:bold">celix_status_t</span> status <span style="color:#666">=</span> CELIX_SUCCESS;
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">struct</span> dm_exmpl_activator <span style="color:#666">*</span>act <span style="color:#666">=</span> (<span style="color:#a2f;font-weight:bold">struct</span> dm_exmpl_activator<span style="color:#666">*</span>)userData;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> act<span style="color:#666">-&gt;</span>exmpl <span style="color:#666">=</span> <span style="color:#00a000">exmpl_create</span>();
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">if</span> (act<span style="color:#666">-&gt;</span>exmpl <span style="color:#666">!=</span> <span style="color:#a2f">NULL</span>) {
</span></span><span style="display:flex;"><span> dm_component_pt cmp;
</span></span><span style="display:flex;"><span> <span style="color:#00a000">component_create</span>(context, <span style="color:#b44">&#34;Example Component&#34;</span>, <span style="color:#666">&amp;</span>cmp);
</span></span><span style="display:flex;"><span> <span style="color:#00a000">component_setImplementation</span>(cmp, act<span style="color:#666">-&gt;</span>exmpl);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#00a000">dependencyManager_add</span>(manager, cmp);
</span></span><span style="display:flex;"><span> } <span style="color:#a2f;font-weight:bold">else</span> {
</span></span><span style="display:flex;"><span> status <span style="color:#666">=</span> CELIX_ENOMEM;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">return</span> status;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#0b0;font-weight:bold">celix_status_t</span> <span style="color:#00a000">dm_destroy</span>(<span style="color:#0b0;font-weight:bold">void</span> <span style="color:#666">*</span> userData, bundle_context_pt context, dm_dependency_manager_pt manager) {
</span></span><span style="display:flex;"><span> <span style="color:#0b0;font-weight:bold">celix_status_t</span> status <span style="color:#666">=</span> CELIX_SUCCESS;
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">struct</span> dm_exmpl_activator <span style="color:#666">*</span>act <span style="color:#666">=</span> (<span style="color:#a2f;font-weight:bold">struct</span> dm_exmpl_activator<span style="color:#666">*</span>)userData;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">if</span> (act<span style="color:#666">-&gt;</span>exmpl <span style="color:#666">!=</span> <span style="color:#a2f">NULL</span>) {
</span></span><span style="display:flex;"><span> <span style="color:#00a000">exmpl_destroy</span>(act<span style="color:#666">-&gt;</span>exmpl);
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span> <span style="color:#00a000">free</span>(act);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#a2f;font-weight:bold">return</span> CELIX_SUCCESS;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="dependency-manager-shell-support">Dependency Manager Shell support</h3>
<p>There is support for retrieving information of the dm components with
use of the <code>dm</code> command. This command will print all known dm component,
their state, provided interfaces and required interfaces.</p>
<h3 id="references">References</h3>
<p>For more information examples please see</p>
<ul>
<li><a href="public/include">The Dependency Manager API</a>: The dependency manager header files</li>
<li><a href="../documents/getting_started/using_services_with_c.html">Getting Started: Using Service with C</a>: A introduction how to work with services using the dependency manager</li>
<li><a href="../examples/dm_example">Dm example</a>: A DM example.</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<footer class="py-3 bg-secondary">
<div class="container">
<div class="row">
<div class="col-md-8 text-center">
<p class="m-0 text-white">
Copyright &copy; 2023 The Apache Software Foundation, Licensed under
the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
<br>
Apache Celix, Celix, Apache, the Apache feather logo and the Apache Celix logo are trademarks of The Apache Software Foundation.
</p>
</div>
<div class="col-md-4 text-center">
<a href="https://www.apache.org/events/current-event.html" target="_blank">
<img src="https://www.apache.org/events/current-event-234x60.png" title="Apache Event" width="234" height="60" border="0">
</a>
</div>
</div>
</div>
</footer>
<script src="/assets/js/jquery.min.js"></script>
<script src="/assets/js/bootstrap.bundle.min.js"></script>
</body>
</html>