blob: 8fb3905314c585e9d9e414860da3a49051b9df23 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!--
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.
-->
<head>
<title>Apache Felix - iPOJO Composition Tutorial</title>
<link rel="icon" href="/res/favicon.ico">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="The most powerful component model for OSGi">
<link href="/ipojo/web/bootstrap/css/bootstrap-cerulean.css" rel="stylesheet">
<link href="/ipojo/web/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
<link href="/ipojo/web/bootstrap/css/font-awesome.min.css" rel="stylesheet">
<link href="/ipojo/web/style.css" rel="stylesheet">
<!-- Overide alert's colors -->
<link href="/ipojo/web/bootstrap/css/alert.css" rel="stylesheet">
<link rel="stylesheet" href="/ipojo/web/github.css" type="text/css" media="all">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="/ipojo/web/bootstrap/js/bootstrap.min.js"></script>
</head>
<body data-spy="scroll" data-target=".subnav">
<div class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="/documentation/subprojects/apache-felix-ipojo.html">Apache Felix iPOJO</a>
<div class="nav-collapse" id="main-menu">
<ul class="nav" id="main-menu-left">
<li><a href="/documentation/subprojects/apache-felix-ipojo/ipojo-news.html">News</a></li>
<li><a href="http://felix.apache.org/downloads.cgi">Downloads</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials <b class="caret"></b></a>
<ul class="dropdown-menu" id="tutorials-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-why-choose-ipojo.html">Why choose iPOJO</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-successstories.html">Success stories</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-feature-overview.html">Features</a></li>
<li class="divider"></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/ipojo-in-10-minutes.html">iPOJO in 10 minutes</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/how-to-use-ipojo-annotations.html">Using Annotations</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/ipojo-hello-word-maven-based-tutorial.html">Maven tutorial</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/ipojo-advanced-tutorial.html">Advanced tutorial</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/apache-felix-ipojo-dosgi.html">Using Distributed OSGi</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/ipojo-composition-tutorial.html">Application Composition</a></li>
</ul>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Documentation <b class="caret"></b></a>
<ul class="dropdown-menu" id="user-guide-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/service-requirement-handler.html">Requiring a service</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/providing-osgi-services.html">Providing a service</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/lifecycle-callback-handler.html">Lifecycle management</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/configuration-handler.html">Configuration</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/architecture-handler.html">Introspection</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/controller-lifecycle-handler.html">Impacting the lifecycle</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/injecting-bundle-context.html">Accessing the Bundle Context</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.html">Creating instances</a></li>
<li class="divider"></li>
<li class="dropdown-submenu">
<a tabindex="-1" href="#">External <em>handlers</em></a>
<ul class="dropdown-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/event-admin-handlers.html">Asynchronous communication</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/ipojo-jmx-handler.html">JMX management</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/extender-pattern-handler.html">Extender pattern</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/white-board-pattern-handler.html">Whiteboard pattern</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/temporal-service-dependency.html">Temporal dependencies</a></li>
</ul>
</li>
<li class="dropdown-submenu">
<a tabindex="-1" href="#">Configuration Admin &amp; Factories</a>
<ul class="dropdown-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/combining-ipojo-and-configuration-admin.html">iPOJO and config admin</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/ipojo-factory-service.html">Using the iPOJO Factory service</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/how-to-use-ipojo-factories.html">Factories and Instances</a></li>
</ul>
</li>
<li class="divider"></li>
<li class="dropdown-submenu">
<a tabindex="-1" href="#">Advanced topics</a>
<ul class="dropdown-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/instance-vs-service-controller.html">Instance vs. Service Controllers</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/service-binding-interceptors.html">Service Binding Interceptors</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/using-xml-schemas.html">XML Schemas</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-api.html">Using the iPOJO API</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/constructing-pojo-objects-with-factory-methods.html">Constructing service objects with factory methods</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/using-ipojo-introspection-api.html">Using the introspection API</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-testing-components.html">Testing components</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/using-stereotypes.html">Using @Stereotypes</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-eclipse-integration.html">Eclipse Integration</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/ipojo-extender-configuration.html">Configuring iPOJO's Extender</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-faq.html">FAQ</a></li>
<li class="divider"></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-devguide/how-to-write-your-own-handler.html">Handler development</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-devguide/how-to-use-ipojo-manipulation-metadata.html">Manipulation Metadata </a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-devguide/dive-into-the-ipojo-manipulation-depths.html">Dive into the iPOJO Manipulation depths</a></li>
<li><a href="http://felix.apache.org/ipojo/api/1.12.1">Javadoc</a></li>
</ul>
</li>
</ul>
</li>
<li class="dropdown" id="tools-menu">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Tools <b class="caret"></b></a>
<ul class="dropdown-menu" id="swatch-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-tools/ipojo-ant-task.html">Ant Task</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-tools/ipojo-maven-plug-in.html">Maven Plugin</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-tools/ipojo-arch-command.html">Architecture commands</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-tools/apache-felix-ipojo-online-manipulator.html">Online Manipulator</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-tools/ipojo-webconsole-plugin.html">Webconsole plugin</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-tools/ipojo-karaf-feature.html">Apache Karaf Features</a></li>
</ul>
</li>
<li class="dropdown" id="community-menu">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Community <b class="caret"></b></a>
<ul class="dropdown-menu" id="swatch-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/ipojo-support.html">Support</a></li>
<li><a href="http://www.apache.org/">ASF</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">Sponsors</a></li>
</ul>
</li>
<li class="dropdown" id="misc-menu">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Misc <b class="caret"></b></a>
<ul class="dropdown-menu" id="swatch-menu">
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-supportedvms.html">Supported JVMs</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-supportedosgi.html">Supported OSGi Implementations</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/articles-and-presentations.html">Article & Presentations</a></li>
<li><a href="/documentation/subprojects/apache-felix-ipojo/developing-camel-mediators-with-ipojo.html">Developping Camel mediators with iPOJO</a></li>
</ul>
</li>
</ul>
<ul class="nav pull-right" id="main-menu-right">
<li><a rel="tooltip" target="_blank" href="http://felix.apache.org">Apache Felix <i class="icon-share-alt"></i></a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="content">
<style type="text/css">
/* The following code is added by mdx_elementid.py
It was originally lifted from http://subversion.apache.org/style/site.css */
/*
* Hide class="elementid-permalink", except when an enclosing heading
* has the :hover property.
*/
.headerlink, .elementid-permalink {
visibility: hidden;
}
h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
<h1 id="ipojo-composition-tutorial">iPOJO Composition Tutorial<a class="headerlink" href="#ipojo-composition-tutorial" title="Permanent link">&para;</a></h1>
<p><em>This page describes how works the composition mechanisms provided by iPOJO and how to use it. this feature allows you to design applications that will natively support the dynamism and the evolution.</em></p>
<div class="toc">
<ul>
<li><a href="#ipojo-composition-tutorial">iPOJO Composition Tutorial</a><ul>
<li><a href="#why-providing-a-composition-layer">Why providing a composition layer?</a><ul>
<li><a href="#what-about-privacy">What about privacy?</a></li>
</ul>
</li>
<li><a href="#the-different-types-of-composition-in-the-osgi-world">The different types of composition in the OSGi world</a><ul>
<li><a href="#intra-bundle-composition">Intra-bundle composition</a></li>
<li><a href="#service-based-composition">Service-based composition</a></li>
</ul>
</li>
<li><a href="#the-ipojo-composition-theory-for-the-dummies">The iPOJO composition theory for the dummies</a></li>
<li><a href="#the-service-context-concept">The service context concept</a></li>
<li><a href="#downloads">Downloads</a></li>
<li><a href="#lets-start-with-a-first-composition">Let's start with a first composition</a></li>
<li><a href="#importing-a-service-inside-a-composite">Importing a service inside a composite</a></li>
<li><a href="#abstracting-implementation-composing-services">Abstracting implementation... Composing services</a></li>
<li><a href="#publishing-services">Publishing services</a></li>
<li><a href="#hierarchical-composites">Hierarchical composites</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</li>
</ul>
</div>
<h2 id="why-providing-a-composition-layer">Why providing a composition layer?<a class="headerlink" href="#why-providing-a-composition-layer" title="Permanent link">&para;</a></h2>
<p>iPOJO aims to simplify the creation of OSGi (dynamic) applications. Creating such as applications is basically a two steps process:</p>
<ul>
<li>Developing services and components</li>
<li>Assembling them together to create the application</li>
</ul>
<p>To tackle the first step, iPOJO provides an easy-to-use development model. But, this does not help to design the application. To conduct the second step, iPOJO provides a composition language allowing to:</p>
<ul>
<li>Assemble components and services together</li>
<li>Assert service isolation inside a composition</li>
<li>Hide/Abstract implementations </li>
</ul>
<h3 id="what-about-privacy">What about privacy?<a class="headerlink" href="#what-about-privacy" title="Permanent link">&para;</a></h3>
<p>Service or component composition has a stringent requirement. How to isolate components and services of an application to avoid side effects as an unexpected access to a used service ...iPOJO composites just provide an isolation mechanism. Services provided inside a composite ARE NOT published globally (inside the OSGi service registry). So, only the component instances living in the same composite can access to those services.
However, it is also possible to import a service from the parent/global service registry, as well as to export a service to the parent (i.e. superior) composite.</p>
<h2 id="the-different-types-of-composition-in-the-osgi-world">The different types of composition in the OSGi world<a class="headerlink" href="#the-different-types-of-composition-in-the-osgi-world" title="Permanent link">&para;</a></h2>
<p>Basically there is two types of composition in OSGi:</p>
<ul>
<li>The intra-bundle composition</li>
<li>The service-based composition</li>
</ul>
<h3 id="intra-bundle-composition">Intra-bundle composition<a class="headerlink" href="#intra-bundle-composition" title="Permanent link">&para;</a></h3>
<p>The intra-bundle composition is the policy followed by Spring-DM. Each bundle contains components. These components can require and provide services from the global (OSGi) registry. Moreover, these components can collaborate together inside the bundle without providing/requiring services. So the isolation scope of intra-bundle composition is the <em>bundle</em>. This type of composition allows providing coarse-grain services provided by the collaboration of several components. However, it is not possible to update one of those components, as the update unity is the bundle.</p>
<h3 id="service-based-composition">Service-based composition<a class="headerlink" href="#service-based-composition" title="Permanent link">&para;</a></h3>
<p>There are two types of service composition. The behavioral service composition is like <a href="http://www.ibm.com/developerworks/library/specification/ws-bpel/">BPEL</a> for the web services. An orchestrator supervises the execution and the collaboration of services like:</p>
<ol>
<li>Call service A</li>
<li>Call service B </li>
<li>...</li>
</ol>
<p>The second type of service composition is the structural service composition. This aims to provide a kind of Architecture Description Language for service-based applications. iPOJO follows this trend. This way as several advantages:</p>
<ul>
<li>Avoids coupling a composition to specific implementation, and so it supports the dynamic substitution</li>
<li>Allows the evolution of used services and components at runtime</li>
</ul>
<p>This is also the way followed by <a href="http://www.ibm.com/developerworks/library/specification/ws-sca/">SCA</a>. However, SCA does not specify how the dynamism should be handled.</p>
<h2 id="the-ipojo-composition-theory-for-the-dummies">The iPOJO composition theory for the dummies<a class="headerlink" href="#the-ipojo-composition-theory-for-the-dummies" title="Permanent link">&para;</a></h2>
<p>The distinction between component types and instances
When you declare a <code>&lt;component&gt;</code> (or a <code>&lt;composite&gt;</code>) in your metadata, you're declaring a component type. Then you declare instances from these component types. This mechanism is critic for the iPOJO composition. Indeed, inside a composite, you're able to create instances from any (public) component types (Refer to the <a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/how-to-use-ipojo-factories.html">Factory</a> web page for further details).
On the top of this mechanism, we can define the concept of service implementation. A service implementation is just a component type where the instances provide a service. For example, if the instance from a component type provides the service S, the component type is a service implementation of S, and so can be used to create a provider of S. </p>
<h2 id="the-service-context-concept">The service context concept<a class="headerlink" href="#the-service-context-concept" title="Permanent link">&para;</a></h2>
<p>The service context is the concept allowing service isolation. OSGi bundle context allows accessing both to bundle-based functionality (like <code>loadClass</code>) and to the service registry. However, OSGi defines only one service registry, accessible by any bundles. iPOJO splits these two interaction types. Instances receive an iPOJO Bundle Context delegating bundle-related methods to the "regular" bundle context, and service-related methods to a service context. This service context can access to the OSGi service registry or to a new one. Each composition instances have a service registry. Instances creates inside the composition used this service registry through received the iPOJO Bundle Context. </p>
<h2 id="downloads">Downloads<a class="headerlink" href="#downloads" title="Permanent link">&para;</a></h2>
<p>Download the <a href="http://people.apache.org/~clement/ipojo/tutorials/composite/composite-tutorial.zip">archive</a>. This archive contains:</p>
<ul>
<li>The different applications and component types implemented in this tutorial</li>
<li>A preconfigured version of Felix</li>
<li>Deployment scripts</li>
</ul>
<p>Launch <code>ant</code> from the base directory of the unzipped archive to create every bundles. Then, you can test the different examples by copying and pasting commands from the <code>script.txt</code> file (in the felix folder) in the Felix shell.</p>
<h2 id="lets-start-with-a-first-composition">Let's start with a first composition<a class="headerlink" href="#lets-start-with-a-first-composition" title="Permanent link">&para;</a></h2>
<p>In the <a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/ipojo-in-10-minutes.html">iPOJO in 10 minutes</a> tutorial, we created an application checking a sentence against dictionaries. We'll reuse this simple application in this tutorial.
So first, we need to implements several component types:</p>
<ul>
<li>The dictionary service implementation, containing words</li>
<li>The Check service implementation, providing methods to check words against dictionaries</li>
<li>And the client GUI, using a Check Service to indicate misspelled words.</li>
</ul>
<p>We will reuse the same implementation than in the previous tutorial. The current application is designed as follow:</p>
<p><img src="app1.png"></p>
<p>However, imagine that you want to isolate services provided and required by your application. For example, you want to isolate a stateful service or a critical (private) resource. </p>
<p>So, let's imagine a second version of our spellchecker application. In this application, the dictionary service, and the checker service are isolated inside a composite. So, those services will be accessible only from instances living in the composite. The GUI will also be instantiated inside the composite. The composition will be something like:</p>
<p><img src="app2.png"></p>
<p>The descriptor of this application is:</p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo&gt;</span>
<span class="c">&lt;!-- Declares a composition --&gt;</span>
<span class="nt">&lt;composite</span> <span class="na">name=</span><span class="s">&quot;composition1&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the English dictionary --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.english.EnglishDictionary&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the Checker --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.checker.SpellCheck&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the GUI --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.gui.SpellCheckerGui&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/composite&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of our composition --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;composition1&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<p>First, a composite type is declared inside an iPOJO descriptor. A composite contain always a <code>name</code> attribute, which is the component type name. Inside the <code>&lt;composite&gt;&lt;/composite&gt;</code>, three instances are declared: the three instances used by our application. Remark that these instances are declared as 'regular' instances. The <code>component</code> attribute indicates the component type to use. Instances can be configured as regular iPOJO instances. Finally, an instance of our type is also declared. </p>
<p>To execute our composition, go in the felix directory and launch the following command:</p>
<div class="codehilite"><pre>java -jar bin/felix.jar
</pre></div>
<p>This version of Felix starts with the iPOJO framework, the iPOJO Arch command and the composite support. So, we just need to install our component types and the composition.</p>
<p>In the Felix prompt, launch the following commands:</p>
<div class="codehilite"><pre>start file:../spell.services/output/spell.services.jar
start file:../spell.english/output/spell.english.jar
start file:../spell.checker/output/spell.checker.jar
start file:../spell.checker.gui/output/spell.checker.gui.jar
</pre></div>
<p>Those commands deploy the component types. Remark that no 'functional' (i.e. neither Check service, nor Dictionary service) services are provided. Deployed bundles provide only iPOJO Factory services:</p>
<div class="codehilite"><pre>-&gt; inspect s c
System Bundle <span class="o">(</span>0<span class="o">)</span> provides:
---------------------------
org.osgi.service.startlevel.StartLevel
org.osgi.service.packageadmin.PackageAdmin
Apache Felix Shell Service <span class="o">(</span>1<span class="o">)</span> provides:
----------------------------------------
...
Apache Felix Bundle Repository <span class="o">(</span>3<span class="o">)</span> provides:
--------------------------------------------
org.osgi.service.obr.RepositoryAdmin
iPOJO <span class="o">(</span>4<span class="o">)</span> provides:
-------------------
...
iPOJO Composite <span class="o">(</span>6<span class="o">)</span> provides:
-----------------------------
...
spell.english <span class="o">(</span>8<span class="o">)</span> provides:
---------------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
spell.checker <span class="o">(</span>9<span class="o">)</span> provides:
---------------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
spell.checker.gui <span class="o">(</span>10<span class="o">)</span> provides:
-------------------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
</pre></div>
<p>Now, when can deploy our composition:</p>
<div class="codehilite"><pre>start file:../example1/output/composition1.jar
</pre></div>
<p>Once deployed and started, the fancy GUI appears:</p>
<p><img src="ss-comp.png"></p>
<p>Now, you can check that the functional services are not unavailable outside the composite:</p>
<div class="codehilite"><pre>-&gt; inspect s c
System Bundle <span class="o">(</span>0<span class="o">)</span> provides:
---------------------------
org.osgi.service.startlevel.StartLevel
org.osgi.service.packageadmin.PackageAdmin
Apache Felix Shell Service <span class="o">(</span>1<span class="o">)</span> provides:
----------------------------------------
...
Apache Felix Bundle Repository <span class="o">(</span>3<span class="o">)</span> provides:
--------------------------------------------
org.osgi.service.obr.RepositoryAdmin
iPOJO <span class="o">(</span>4<span class="o">)</span> provides:
-------------------
...
iPOJO Composite <span class="o">(</span>6<span class="o">)</span> provides:
-----------------------------
...
spell.english <span class="o">(</span>8<span class="o">)</span> provides:
---------------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
spell.checker <span class="o">(</span>9<span class="o">)</span> provides:
---------------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
spell.checker.gui <span class="o">(</span>10<span class="o">)</span> provides:
-------------------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
Bundle 11 provides:
-------------------
org.apache.felix.ipojo.Factory, org.osgi.service.cm.ManagedServiceFactory
</pre></div>
<p>Of course, if you stop a bundle providing a required service type, the application is stopped:</p>
<div class="codehilite"><pre>-&gt; stop 8
-&gt; start 8
</pre></div>
<p>Then, the application also supports component type update. However the component type name must not change. We will see later how we can avoid this issue by abstracting implementations.</p>
<h2 id="importing-a-service-inside-a-composite">Importing a service inside a composite<a class="headerlink" href="#importing-a-service-inside-a-composite" title="Permanent link">&para;</a></h2>
<p>Let's imagine a second version of the checker service implementation (spell.checker-v2). This implementation removes the trace when wrong words are detected. Indeed, this implementation uses a log service to store such kind of errors. </p>
<p>If we use this implementation, we need to make a log service available inside the composite. Else, the checker will not be valid. To achieve this, use the following composite:</p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo&gt;</span>
<span class="c">&lt;!-- Declares a composition --&gt;</span>
<span class="nt">&lt;composite</span> <span class="na">name=</span><span class="s">&quot;composition2&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the English dictionary --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.english.EnglishDictionary&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the Checker --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.checker.SpellCheck&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the GUI --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.gui.SpellCheckerGui&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Imports the log service --&gt;</span>
<span class="nt">&lt;subservice</span> <span class="na">action=</span><span class="s">&quot;import&quot;</span>
<span class="na">specification=</span><span class="s">&quot;org.osgi.service.log.LogService&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/composite&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of our composition --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;composition2&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<p>This composite just adds a <code>subservice</code> nested element. This subservice allows importing a service inside the composite. The <code>action</code> attribute specifies that we want to import the service from the parent scope (i.e. superior). The <code>specification</code> attribute indicates the required service. </p>
<p><img src="app3.png"></p>
<p>Now, relaunch Felix and enter another profile name (<code>composition2</code> for example). Once started, executes the following commands:</p>
<div class="codehilite"><pre>start file:../spell.services/output/spell.services.jar
start file:../spell.english/output/spell.english.jar
start file:../spell.checker-v2/output/spell.checker-v2.jar
start file:../spell.checker.gui/output/spell.checker.gui.jar
start file:../example2/output/composition2.jar
</pre></div>
<p>Those commands deploy required component type (note that we deploy spell.checker-v2) and an implementation of the OSGi Log Service. When you execute the last command, the fancy interface re-appears. </p>
<p>Try to enter a wrong word (as <code>composite</code>), and click on the check button. The trace does no more appear... the message is logged inside the log service.
Of course, such composite support dynamism. Try the following scenario</p>
<div class="codehilite"><pre>stop 9
start 9
stop 10
start 10
</pre></div>
<p>When the log service is stopped, the GUI disappears. In fact, the service can no more be imported, and so, the composition becomes invalid. When you stop a bundle containing a used component type, the same behavior occurs.</p>
<p>Like in the previous example, you can check that only the log service is globally available. Other services are isolated inside the composite.
In this case the parent scope is the OSGi service registry, but composite can also contain other composite. In such context, the import tracks services from the superior composite. An example of hierarchical composition is described later in this tutorial.</p>
<div class="alert aert-success">
<strong>Service Resolution</strong>
<p>
To tackle implementation service dependency resolution issues, iPOJO instances track services inside the composite but also in the global service context (OSGi service registry). This feature allows avoiding the declaration of common service import published in the OSGi service registry.
</p>
</div>
<h2 id="abstracting-implementation-composing-services">Abstracting implementation... Composing services<a class="headerlink" href="#abstracting-implementation-composing-services" title="Permanent link">&para;</a></h2>
<p>We saw in the first composition that we depend on specific component types. This can be avoided by specifying the composition in term of services instead of component types. So, every available service implementation can be used. Moreover, if the used one disappears, another one can be immediately used to replace the missing service. Let's illustrate this.</p>
<p>In the first composition, we create an instance of the English dictionary service implementation. We can remove this coupling to this specific implementation. To do this, we will target any implementation of the dictionary service regardless the language. </p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo&gt;</span>
<span class="c">&lt;!-- Declares a composition --&gt;</span>
<span class="nt">&lt;composite</span> <span class="na">name=</span><span class="s">&quot;composition3&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the English dictionary --&gt;</span>
<span class="nt">&lt;subservice</span> <span class="na">action=</span><span class="s">&quot;instantiate&quot;</span>
<span class="na">specification=</span><span class="s">&quot;spell.services.DictionaryService&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the Checker --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.checker.SpellCheck&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the GUI --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.gui.SpellCheckerGui&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/composite&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of our composition --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;composition3&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<p>The previous composition instantiates a dictionary service. This means that the composite looks for an implementation of the Dictionary service and creates an instance of this implementation (i.e. component type) inside the composition.
If several implementations are available, the composite chooses one, and switches to another one if the used implementation becomes unavailable.</p>
<p><img src="app4.png"></p>
<p>To execute this composition, launch Felix and execute the following command:</p>
<div class="codehilite"><pre>start file:../spell.services/output/spell.services.jar
start file:../spell.english/output/spell.english.jar
start file:../spell.checker/output/spell.checker.jar
start file:../spell.checker.gui/output/spell.checker.gui.jar
start file:../example3/output/composition3.jar
</pre></div>
<p>These commands deploy component types and the composition. Only one implementation of the dictionary service is available (English). You can check this by executing the <code>service 8</code> command.</p>
<div class="codehilite"><pre>-&gt; inspect s c 9
spell.english <span class="o">(</span>9<span class="o">)</span> provides:
---------------------------
component.class <span class="o">=</span> spell.english.EnglishDictionary
component.description <span class="o">=</span> &lt;unknown value <span class="nb">type</span>&gt;
component.properties <span class="o">=</span> &lt;unknown value <span class="nb">type</span>&gt;
component.providedServiceSpecifications <span class="o">=</span> spell.services.DictionaryService
factory.name <span class="o">=</span> spell.english.EnglishDictionary
factory.state <span class="o">=</span> 1
<span class="nv">objectClass</span> <span class="o">=</span> org.apache.felix.ipojo.Factory,
org.osgi.service.cm.ManagedServiceFactory
service.id <span class="o">=</span> 39
service.pid <span class="o">=</span> spell.english.EnglishDictionary
</pre></div>
<p>Note the <code>component.providedServiceSpecifications</code> property indicating provided services.
Now deploy another implementation of the dictionary service, such as the French dictionary service ☺</p>
<div class="codehilite"><pre>start file:../spell.french/output/spell.french.jar
</pre></div>
<p>Write <code>welcome</code> in the GUI and then check. The word is correctly spelled. Then, stop the bundle providing the English dictionary.</p>
<div class="codehilite"><pre>stop 9
</pre></div>
<p>Write <code>welcome</code> in the GUI, and check. The word is misspelled! Try to write <code>bienvenue</code> and check. The word is correctly spelled. This means that the composite has substitutes the previous English dictionary by the French one. This one will be use until it disappears. If you stop the bundle containing this implementation, the composite becomes invalid.</p>
<h2 id="publishing-services">Publishing services<a class="headerlink" href="#publishing-services" title="Permanent link">&para;</a></h2>
<p>A composition can also provide services. iPOJO composites support two methods to provide services :</p>
<ul>
<li>The service export: re-export a service from the composite to the parent context</li>
<li>The service implementation: the composite computes a delegation scheme to delegate every method of the provided service on internal entities (services and instances)</li>
</ul>
<p>This section addresses the export. Exporting a service is the opposite of the service import. It tracks services from the composites to publish it in the parent (superior) context.
So, let's imagine a fourth version of our application. In this application, the GUI is externalized and lives in the global context (i.e. OSGi). So, the composition exports the spell checker service. </p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo&gt;</span>
<span class="c">&lt;!-- Declares a composition --&gt;</span>
<span class="nt">&lt;composite</span> <span class="na">name=</span><span class="s">&quot;composition4&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the English dictionary --&gt;</span>
<span class="nt">&lt;subservice</span> <span class="na">action=</span><span class="s">&quot;instantiate&quot;</span>
<span class="na">specification=</span><span class="s">&quot;spell.services.DictionaryService&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the Checker --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.checker.SpellCheck&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Export the SpellChecker service --&gt;</span>
<span class="nt">&lt;provides</span> <span class="na">action=</span><span class="s">&quot;export&quot;</span>
<span class="na">specification=</span><span class="s">&quot;spell.services.SpellChecker&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/composite&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of our composition --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;composition4&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the GUI in the global context --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.gui.SpellCheckerGui&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<p>In the previous composition, the composite exports the spell checker service. Moreover, the GUI is also created but in the global context. At runtime, the result will be as following:</p>
<p><img src="app5.png"></p>
<p>The composite published the spell checker service in the OSGi service registry. The GUI tracks this service in the OSGi service registry too.
To execute this composition, launch Felix and execute following the commands:</p>
<div class="codehilite"><pre>start file:../spell.services/output/spell.services.jar
start file:../spell.english/output/spell.english.jar
start file:../spell.checker/output/spell.checker.jar
start file:../spell.checker.gui/output/spell.checker.gui.jar
start file:../example4/output/composition4.jar
</pre></div>
<p>You can check that the composition exports the service with the following command:</p>
<div class="codehilite"><pre>-&gt; services 12
Bundle 12 provides:
-------------------
component.description <span class="o">=</span> &lt;unknown value <span class="nb">type</span>&gt;
component.properties <span class="o">=</span> &lt;unknown value <span class="nb">type</span>&gt;
component.providedServiceSpecifications <span class="o">=</span> spell.services.SpellChecker
factory.name <span class="o">=</span> composition4
factory.state <span class="o">=</span> 1
<span class="nv">objectClass</span> <span class="o">=</span> org.apache.felix.ipojo.Factory,
org.osgi.service.cm.ManagedServiceFactory
service.id <span class="o">=</span> 36
service.pid <span class="o">=</span> composition4
----
factory.name <span class="o">=</span> composition4
instance.name <span class="o">=</span> composition4-0
<span class="nv">objectClass</span> <span class="o">=</span> spell.services.SpellChecker
service.id <span class="o">=</span> 37
</pre></div>
<p>So, now you can play with dynamism. Stop the bundle containing the Check service implementation. The GUI disappears. Restart it. The GUI reappears. Now, stop the bundle containing the GUI implementation. The checker service stills available. Indeed, the GUI is no more inside the composition, and so stills valid despite the unavailability of the GUI:</p>
<div class="codehilite"><pre>-&gt; stop 9
-&gt; start 9
-&gt; stop 11
-&gt; inspect s c 12
Bundle 12 provides:
-------------------
component.description <span class="o">=</span> &lt;unknown value <span class="nb">type</span>&gt;
component.properties <span class="o">=</span> &lt;unknown value <span class="nb">type</span>&gt;
component.providedServiceSpecifications <span class="o">=</span> spell.services.SpellChecker
factory.name <span class="o">=</span> composition4
factory.state <span class="o">=</span> 1
<span class="nv">objectClass</span> <span class="o">=</span> org.apache.felix.ipojo.Factory,
org.osgi.service.cm.ManagedServiceFactory
service.id <span class="o">=</span> 36
service.pid <span class="o">=</span> composition4
----
factory.name <span class="o">=</span> composition4
instance.name <span class="o">=</span> composition4-0
<span class="nv">objectClass</span> <span class="o">=</span> spell.services.SpellChecker
service.id <span class="o">=</span> 41
-&gt;
</pre></div>
<h2 id="hierarchical-composites">Hierarchical composites<a class="headerlink" href="#hierarchical-composites" title="Permanent link">&para;</a></h2>
<p>A composition can also contain others compositions. Let's imagine a variation of the latest application. In this case, we define a composite containing the GUI and the previous composite.</p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo&gt;</span>
<span class="c">&lt;!-- Declares the same composition than the latest one --&gt;</span>
<span class="nt">&lt;composite</span> <span class="na">name=</span><span class="s">&quot;composition4&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the English dictionary --&gt;</span>
<span class="nt">&lt;subservice</span> <span class="na">action=</span><span class="s">&quot;instantiate&quot;</span>
<span class="na">specification=</span><span class="s">&quot;spell.services.DictionaryService&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the Checker --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.checker.SpellCheck&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Exports the SpellChecker service --&gt;</span>
<span class="nt">&lt;provides</span> <span class="na">action=</span><span class="s">&quot;export&quot;</span>
<span class="na">specification=</span><span class="s">&quot;spell.services.SpellChecker&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/composite&gt;</span>
<span class="c">&lt;!-- Declares another composition containing an instance of the previous </span>
<span class="c"> composition and an instance of the GUI</span>
<span class="c"> --&gt;</span>
<span class="nt">&lt;composite</span> <span class="na">name=</span><span class="s">&quot;composition5&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Instantiates the previous composition</span>
<span class="c"> You can access to composition by following the</span>
<span class="c"> same way as for other types</span>
<span class="c"> --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;composition4&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of the GUI in the composite --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;spell.gui.SpellCheckerGui&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/composite&gt;</span>
<span class="c">&lt;!-- Instantiates an instance of our composition --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;composition5&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<p>The <code>composition5</code> contains an instance of the <code>composition4</code> and of the GUI. So the spell checker service exported by the composition4 is published inside the service context of the <code>composite 5</code> (the parent context). The GUI instance lives in this service context, and so can access to the exported Spell checker service.</p>
<p><img src="app6.png"></p>
<p>To execute this composition, restart Felix and launch the following commands:</p>
<div class="codehilite"><pre>start file:../spell.services/output/spell.services.jar
start file:../spell.english/output/spell.english.jar
start file:../spell.checker/output/spell.checker.jar
start file:../spell.checker.gui/output/spell.checker.gui.jar
start file:../example5/output/composition5.jar
</pre></div>
<p>You can check that the composite does no more publish the spell checker service in the OSGi service registry.</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">&para;</a></h2>
<p>This page has presented how to use iPOJO composition model. Several topics were not addressed and will be added shortly:</p>
<ul>
<li>Dynamic service implementation</li>
<li>The dependency model</li>
<li><em>Composable</em> services and composition consistency</li>
<li>Context-awareness</li>
</ul>
<p>Subscribe to the Felix users mailing list by sending a message to <a href="mailto:users-subscribe@felix.apache.org">users-subscribe@felix.apache.org</a>; after subscribing, email questions or feedback to <a href="mailto:users@felix.apache.org">users@felix.apache.org</a>.</p>
</div>
</div>
<hr/>
<div class="container">
<footer id="footer">
<div class="row">
<div class="trademarkFooter span7">
Apache Felix, Felix, Apache, the Apache feather logo, and the Apache Felix project
logo are trademarks of The Apache Software Foundation. All other marks mentioned
may be trademarks or registered trademarks of their respective owners.
</div>
<div class="timestamp span3 offset2">
Rev. 1700393 by cziegeler on Tue, 1 Sep 2015 06:04:06 +0000
</div>
</div>
</footer>
</div>
</body>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try{
var pageTracker = _gat._getTracker("UA-1518442-4");
pageTracker._trackPageview();
} catch(err) {}
</script>
</html>