blob: 84a20de9d2114ae5fb2be58d500182b36d63c7f6 [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>Apache Celix Services / 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.3.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--osgi--patterns">Apache Celix / OSGi patterns</h1>
<p>There are several design patterns used in Apache Celix and OSGi.</p>
<h2 id="whiteboard-pattern">Whiteboard Pattern</h2>
<p>The whiteboard pattern is a pattern where the act of registering a service is enough to participate in or extend
an existing functionality.<br>
A typical aspect of the whiteboard pattern is that an application should
still resolve and startup even if the bundle or bundles that pick up the whiteboard pattern services are absent.</p>
<p><img src="diagrams/whiteboard_pattern.png" alt="Whiteboard Pattern"></p>
<p>Many Apache Celix services are whiteboard services. For example:</p>
<ul>
<li><code>celix_shell_command_t</code> and <code>celix::IShellCommand</code> services. These services can be
picked up by the <code>Celix::shell</code> bundle, but applications should still work if there is no <code>Celix::shell</code> installed
and started. <br/>
<img src="diagrams/whiteboard_pattern_shell.png" alt="Celix Shell"></li>
<li><code>celix_http_service_t</code> and <code>celix_websocket_service_t</code> services. These services can be picked up by the
<code>Celix::http_admin</code> bundle to provide http url endpoints or websocket url endpoints. <br/>
<img src="diagrams/whiteboard_pattern_http_admin.png" alt="Celix HTTP Admin"></li>
<li><code>celix_log_sink_t</code> services. If there is no <code>Celix::log_admin</code> bundle installed and started, the log sinks
services will never be called, but the application should still work. Note that the <code>Celix::log_admin</code> bundle
also uses a service on demand pattern (see below). <br/>
<img src="diagrams/whiteboard_pattern_log_sink.png" alt="Celix Log Admin"></li>
<li>Services marked as remote service (<code>service.exported.interface=*</code>). These services will work fine
but only as local services - if there are no remote service bundles installed and started.</li>
</ul>
<p>For modularity, the whiteboard pattern is a nice fit, because a whiteboard service admin does not need to know how
many - if any - whiteboard services are going to be provided and how the implementation details work (as long as
the implementation adheres to the service contract).</p>
<p>Whiteboard pattern services are always <a href="https://docs.osgi.org/javadoc/osgi.annotation/8.0.0/org/osgi/annotation/versioning/ConsumerType.html">consumer types</a>, although for Apache Celix interfaces cannot be annotated as
consumer or provider type.</p>
<p>One of the downsides of the whiteboard pattern is that it is not always clear why an application is not working as
expected or what is missing to get the application working as expected. This is because it is not an error
if there are unused services, and as result there is no error to help a user to identify what is missing.</p>
<p>For example: A <code>log_collector</code> bundle which provides a <code>celix_log_sink_t</code> service is installed and started,
so that logging can be collected at in a central log database.
But no logging is added to the central log database. Initially it could seem that the <code>log_collector</code> bundle
does not work, especially because the application will not print any warnings or errors.
But if the <code>Celix::log_admin</code> bundle is not installed and started, the <code>log_collector</code> bundle provided<br>
<code>celix_log_sink_t</code> service will never be called, so installing and starting the <code>Celix::log_admin</code> is the issue
in this example.</p>
<h2 id="extender-pattern">Extender Pattern</h2>
<p>The extender pattern is a design pattern which leverages the concept of resource containing bundles.
With the extender pattern, functionality of an extender bundle can be extended by installing so called extendee bundles.
The extendee bundles contain certain resources files and/or bundle manifest entries which are used by the extender
bundle.</p>
<p><img src="diagrams/extender_pattern.png" alt="Extender Pattern"></p>
<p>An example of the extender pattern is the <code>Celix::http_admin</code> bundle. The extender bundle <code>Celix::http_admin</code>
monitors installed bundles and reads bundle <code>MANIFEST.MF</code> entries for a <code>X-Web-Resource</code> entry.
If a <code>X-Web-Resource</code> entry is found, its value is used to set up new HTTP endpoint in the HTTP server of
the <code>Celix::http_admin</code> bundle using the static web resources of the extendee bundle.</p>
<h3 id="celixhttp_admin-extendee-bundle-example"><code>Celix::http_admin</code> Extendee Bundle Example</h3>
<p>The following example shows how a very simple <code>Celix::http_admin</code> extendee bundle, which provided a minimal
hello world <code>index.html</code> page for the <code>Celix::http_admin</code> to pick up.</p>
<p>Remarks for the <code>Celix::http_admin</code> extendee bundle example:</p>
<ol>
<li>Creates a bundle which will function as an extendee bundle for the <code>Celix::http_admin</code>.</li>
<li>Marks the bundle as a resource-only bundle, i.e. a bundle with no C or C++ activator.</li>
<li>Creates a very simple <code>index.html</code> file in CMake</li>
<li>Adds the <code>index.html</code> file to the <code>http_admin_extendee_bundle</code> bundle in the bundle directory resources.</li>
<li>Adds a <code>X-Web-Resource</code> bundle manifest entry, which marks the bundle as an extendee bundle for the
<code>Celix::http_admin</code> bundle. See <code>Celix::http_admin</code> for more info. Note that <code>$&lt;SEMICOLON&gt;</code> is used,
because a literal <code>;</code> has a special meaning in CMake.</li>
<li>Create a container which installs and starts the <code>Celix::http_admin</code> (extender) bundle and the
<code>http_admin_extendee_bundle</code> (extendee) bundle.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-CMake" data-lang="CMake"><span style="display:flex;"><span><span style="color:#080;font-style:italic">#CMakeLists.txt
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span><span style="color:#a2f">add_celix_bundle</span>(<span style="color:#b44">http_admin_extendee_bundle</span> <span style="color:#080;font-style:italic"># &lt;----------------------------------------------------------------------&lt;1&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span> <span style="color:#b44">VERSION</span> <span style="color:#b44">1.0.0</span>
</span></span><span style="display:flex;"><span> <span style="color:#b44">NO_ACTIVATOR</span> <span style="color:#080;font-style:italic"># &lt;-------------------------------------------------------------------------------------------------&lt;2&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span>)<span style="">
</span></span></span><span style="display:flex;"><span><span style=""></span><span style="color:#a2f">file</span>(<span style="color:#b44">WRITE</span> <span style="color:#b44">&#34;${CMAKE_CURRENT_BINARY_DIR}/index.html&#34;</span> <span style="color:#b44">&#34;&lt;html&gt;&lt;body&gt;Hello World&lt;/body&gt;&lt;/html&gt;&#34;</span>) <span style="color:#080;font-style:italic"># &lt;---------------------&lt;3&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span><span style="color:#a2f">celix_bundle_files</span>(<span style="color:#b44">http_admin_extendee_bundle</span> <span style="color:#b44">&#34;${CMAKE_CURRENT_BINARY_DIR}/index.html&#34;</span> <span style="color:#b44">DESTINATION</span> <span style="color:#b44">resources</span>) <span style="color:#080;font-style:italic"># &lt;----&lt;4&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span><span style="color:#a2f">celix_bundle_headers</span>(<span style="color:#b44">http_admin_extendee_bundle</span> <span style="color:#b44">&#34;X-Web-Resource: /hello$&lt;SEMICOLON&gt;/resources&#34;</span>) <span style="color:#080;font-style:italic"># &lt;------------------&lt;5&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span><span style="">
</span></span></span><span style="display:flex;"><span><span style=""></span><span style="color:#a2f">add_celix_container</span>(<span style="color:#b44">extender_pattern_example_container</span> <span style="color:#080;font-style:italic"># &lt;-----------------------------------------------------------&lt;6&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#080;font-style:italic"></span> <span style="color:#b44">BUNDLES</span>
</span></span><span style="display:flex;"><span> <span style="color:#b44">Celix::http_admin</span>
</span></span><span style="display:flex;"><span> <span style="color:#b44">http_admin_extendee_bundle</span>
</span></span><span style="display:flex;"><span>)<span style="">
</span></span></span></code></pre></div><p>When the <code>extender_pattern_example_container</code> executable is running the web address <code>http://localhost:8080/hello</code>
should show the content of the <code>index.html</code></p>
<h2 id="service-on-demand-sod-pattern">Service on Demand (SOD) Pattern</h2>
<p>A less known Apache Celix / OSGi pattern is the service on demand (SOD) pattern. With the SOD pattern,
services are ad hoc registered at the moment they are requested.</p>
<p>Where the whiteboard pattern can be used to extend functionality in modular and service oriented fashion, the SOD
pattern can be used to use to provide more functional cohesive services to users in a service oriented fashion.</p>
<p>For the SOD pattern, the service filter to request services can be used to extract information about if and how
a service on demand needs to be created.</p>
<p><img src="diagrams/sod_pattern.png" alt="Service On Demand Pattern"></p>
<p>Some Apache Celix bundles use the SOD pattern. For example:</p>
<ul>
<li>The <code>Celix::log_admin</code> bundle creates and registers <code>celix_log_service_t</code> services already preconfigured for
a requested logger name. <br/>
<img src="diagrams/sod_pattern_log_service.png" alt="Celix Log Admin"></li>
<li>The Celix PubSub bundles uses SOD to create and register <code>pubsub_publisher_t</code> services when these are requested
with a valid &ldquo;topic.name&rdquo; and &ldquo;topic.scope&rdquo; filter attribute. For PubSub, the Celix PubSub Topology Manager monitors
the <code>pubsub_publisher_t</code> requests and instructs the available Celix PubSub Admins to create
<code>pubsub_publisher_t</code>. <br/>
<img src="diagrams/sod_pattern_publisher_service.png" alt="Celix PubSub"></li>
<li>The Apache Celix / OSGi remote services uses SOD, by ad hoc imported services only when they are discovered and
requested.</li>
</ul>
<p>SOD services are always <a href="https://docs.osgi.org/javadoc/osgi.annotation/8.0.0/org/osgi/annotation/versioning/ProviderType.html">provider types</a>, although for Apache Celix interfaces cannot be annotated as
consumer or provider type.</p>
<p>For OSGi the <a href="https://docs.osgi.org/javadoc/osgi.core/8.0.0/org/osgi/framework/hooks/service/FindHook.html">FindHook</a>
service can be used to further fine tune which services are visible for bundle requesting a SOD service.
Apache Celix does not yet support the FindHook service.</p>
</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; 2024 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>