blob: 491c826c257bc32028de5591666f4fc883510435 [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 - How to write your own handler</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="how-to-write-your-ipojo-handler">How to write your iPOJO Handler<a class="headerlink" href="#how-to-write-your-ipojo-handler" title="Permanent link">&para;</a></h1>
<p><em>This document explains how developers can use iPOJO extensibility mechanism to extend the (primitive) component instance container. Such extensibility mechanism does not require to modify the iPOJO core.</em></p>
<div class="toc">
<ul>
<li><a href="#how-to-write-your-ipojo-handler">How to write your iPOJO Handler</a><ul>
<li><a href="#ipojo-concepts">iPOJO Concepts</a></li>
<li><a href="#handler-development-basis">Handler development basis</a><ul>
<li><a href="#fundamentals">Fundamentals</a></li>
<li><a href="#declaring-your-handler">Declaring your handler</a></li>
<li><a href="#handler-lifecycle">Handler lifecycle</a></li>
<li><a href="#reading-handler-and-instance-configurations">Reading handler and instance configurations</a></li>
<li><a href="#interacting-with-the-pojo">Interacting with the POJO</a></li>
<li><a href="#using-your-handler">Using your handler</a></li>
</ul>
</li>
<li><a href="#log-handler-example">Log Handler example</a><ul>
<li><a href="#handler-metadata">Handler metadata</a></li>
<li><a href="#handler-implementation">Handler implementation</a><ul>
<li><a href="#loghandler-class">LogHandler class</a></li>
<li><a href="#configure-method">Configure Method</a></li>
<li><a href="#statechanged-method">StateChanged Method</a></li>
</ul>
</li>
<li><a href="#start-and-stop">Start and Stop</a></li>
</ul>
</li>
<li><a href="#handler-packaging">Handler packaging</a><ul>
<li><a href="#handler-usage">Handler usage</a></li>
<li><a href="#playing-with-the-handler">Playing with the handler</a></li>
</ul>
</li>
<li><a href="#properties-handler-example">Properties Handler example</a><ul>
<li><a href="#handler-implementation_1">Handler implementation</a><ul>
<li><a href="#propertieshandler-class">PropertiesHandler class</a></li>
<li><a href="#configure-method_1">Configure Method</a></li>
<li><a href="#the-start-and-stop-methods">The start and stop methods</a></li>
<li><a href="#onget-and-onset-methods">onGet and onSet methods</a></li>
</ul>
</li>
<li><a href="#creating-the-annotation">Creating the annotation</a></li>
<li><a href="#handler-packaging_1">Handler packaging</a></li>
<li><a href="#playing-with-the-handler_1">Playing with the handler</a></li>
</ul>
</li>
<li><a href="#advanced-topics">Advanced topics</a><ul>
<li><a href="#handler-reconfiguration">Handler reconfiguration</a></li>
<li><a href="#describing-your-handler">Describing your handler</a></li>
</ul>
</li>
<li><a href="#handlers-annotations">Handler's annotations</a></li>
<li><a href="#handlers-xsd">Handler's XSD</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</li>
</ul>
</div>
<p>First, iPOJO concepts are briefly explained. The second section explains the steps to create a handler. The two last sections describes the implementation and the usage of two small example handlers : a Log Handler, logging messages inside the OSGi log service, and a Property Handler, injecting properties values inside fields.</p>
<p>The code is available in this <a href="ipojo-handler-tutorial-project.zip">archive file</a>.</p>
<h2 id="ipojo-concepts">iPOJO Concepts<a class="headerlink" href="#ipojo-concepts" title="Permanent link">&para;</a></h2>
<p>iPOJO is a service oriented component model aiming to simplify OSGi applications development. iPOJO is based on the POJO concepts. A POJO is a simple Java class without any dependency on its runtime environment. In iPOJO, POJO are encapsulated in a container managing the relation between the POJO and the external world. This container keeps separated the POJO from the external "wild" world. Moreover, this container can be extended, using handlers.</p>
<p>Basically, iPOJO contains two main concepts: component type and component instance. A component type is a type of component. A component type defines its implementation class, its creation policy, and its container. A component instance is a configured instance of a component type. This instance is created with the component type factory. A component instance inherits of all component type characteristics but has a unique name and its own configuration (set of &lt;key, value&gt;).</p>
<p>Above these concepts, iPOJO runtime will manage component type factories and component instances. Each component instance is managed separately (but the factory can delete them).</p>
<p>A component type declares its container configuration. Each component instance owns its container conform to the component type container configuration. An iPOJO container is composed by an <code>InstanceManager</code>, encapsulating the POJO, on which are plugged handlers. A handler manages one non functional concern. Handlers participate to the component instance lifecycle; can interact with the POJO; can manage relations with external entity like database, or other POJOs... For example, a persistence handler may interact with a database to store and inject POJO state, while an administration handler may use JMX to allow remote configuration of instance properties.</p>
<p><img src="POJO-Container-Handler.png"></p>
<p>iPOJO is an extensible model allowing developer to manage other non functional concerns. Indeed, handlers can be developed singly, without modifying the iPOJO core. At runtime, iPOJO looks for each handler needed by a component instance and plugs an instance of each (required) handler on the container. So iPOJO containers are flexible, light and adaptable to each component. When a needed handler cannot be found, the component instance cannot be created.</p>
<p>An external handler is identified by a namespace. This namespace will be used by developers to refer to the external handler (when he configures its component type) and by iPOJO to instantiate the handler object.</p>
<div class="alert alert-info">
iPOJO core contains 6 "core" handlers managing service providing, service dependencies, lifecycle callbacks, lifecycle controller, instance dynamic configuration, and component instance architecture. Theses handlers follow the same rules than external handlers, except that they use the iPOJO default namespace (i.e. <code>org.apache.felix.ipojo</code>).
</div>
<h2 id="handler-development-basis">Handler development basis<a class="headerlink" href="#handler-development-basis" title="Permanent link">&para;</a></h2>
<h3 id="fundamentals">Fundamentals<a class="headerlink" href="#fundamentals" title="Permanent link">&para;</a></h3>
<p>As explain above, the handler interacts with the POJO, with the component's container and with the external world (e.g. : other components, services, bundles, the OSGi framework, ...). The skeleton of such an agent is defined in iPOJO is defined by the <code>PrimitiveHandler</code> (abstract) class that can be found in the <code>org.apache.felix.ipojo</code> package.</p>
<p>You need to implement the three basic lifecycle methods of this class, but you can extends this model by redefining some other methods (e.g. : to intercept POJO method calls, field accesses, ...).</p>
<h3 id="declaring-your-handler">Declaring your handler<a class="headerlink" href="#declaring-your-handler" title="Permanent link">&para;</a></h3>
<p>You first need to declare your handler, so iPOJO will be able to initialize, configure and use it when needed. First, you must give a name and a namespace to your handler. By doing that, iPOJO can recognize that a certain component uses your handler, so it can initialize it. You need to declare, using the <code>@Handler</code> annotations. You can, of course, declare several handlers, and even declare components using these handlers, in the same bundle.</p>
<div class="codehilite"><pre><span class="nd">@Handler</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;Log&quot;</span><span class="o">,</span> <span class="n">namespace</span> <span class="o">=</span> <span class="n">LogHandler</span><span class="o">.</span><span class="na">NAMESPACE</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">LogHandler</span> <span class="kd">extends</span> <span class="n">PrimitiveHandler</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">NAMESPACE</span> <span class="o">=</span> <span class="s">&quot;org.apache.felix.ipojo.log.handler&quot;</span><span class="o">;</span>
<span class="c1">// ...</span>
<span class="o">}</span>
</pre></div>
<p>Then, you must know that a handler is a component (almost) like standard iPOJO components : it can use other handlers (like core handlers : service requirements, provided services, ...). You can consequently describe your handler's required services, provided services, etc. </p>
<div class="alert alert-info">
In order to use iPOJO annotations processing, the namespace must be a valid package name and the name must be a valid annotation name (without the '@'). Refer to the <a href="#annotations">annotations</a> section.
</div>
<h3 id="handler-lifecycle">Handler lifecycle<a class="headerlink" href="#handler-lifecycle" title="Permanent link">&para;</a></h3>
<p>A handler lifecycle is composed of four different states.</p>
<p><img src="Handler-Lifecycle.png"></p>
<ul>
<li>First, when iPOJO parses the metadata of a bundle, it detects that a certain component type use your handler (using XML qualified names, see the following <em>Using your handler</em> section). When it finds such a reference, it initializes the handler by calling the <code>initializeComponentFactory()</code> method. This method should be static but actually can't be so for some technical reasons. Consequently, a <em>mock</em> instance of the handler is created, the <code>initializeComponentFactory()</code> method is called, and this instance is destroyed. This method aims to check the validity of the component type description, avoiding starting invalid factories.If you override this method, you should here set up the component description (e.g. : common properties, exported services, ...) and check the handler configuration. The parameters passed to this method are the <code>ComponentTypeDescription</code> and the component's <code>Metadata</code> (i.e. : the structure of the component type declaration).</li>
<li>Once your handler has been initialized, iPOJO configures it for each created instance of the using components. The <code>ComponentTypeDescription</code> and the instance specific properties are passed to the <code>configure()</code> method of your handler.This method is mandatory so you have to implement it. Here you should check the handler configuration (if not already done in the <code>initializeComponentFactory()</code> method) and configure the handler with given instance specific properties.</li>
<li>Then, iPOJO starts the handler, following the component instance lifecycle, by calling the <code>start()</code> method. You have to put in this method the activation code of your handler. A freshly started handler is by default in an active state (if all its used handlers, like required services, are in an active state).</li>
<li>Once started, the handler state can be either in a valid or in an invalid state, depending on its used handlers (a handler is an iPOJO component, so it can depend on other handlers, like service dependencies, provided services, ... See the <em>Handler extends Component</em> section). The validity of your handler depends on used handlers status, but it also can be changed in your handler code by using the <code>setValidity()</code> method.</li>
<li>Finally, when the component instance is stopped (generally just before being destroyed), the stop method of the handler is called. Place here the inactivation code of your handler.</li>
</ul>
<div class="alert alert-warning">
Keep in mind that the <code>stop()</code> method of your handler is called when the component instance is stopped (not necessarily destroyed). This instance can be restarted later, so the same instance of your handler must have to ability to restart too.
</div>
<h3 id="reading-handler-and-instance-configurations">Reading handler and instance configurations<a class="headerlink" href="#reading-handler-and-instance-configurations" title="Permanent link">&para;</a></h3>
<p>Your handler need to read how it is configured in the using component type description. The configuration is written in the <code>metadata.xml</code> of the using bundle, but is passed to the <code>initializeComponentFactory()</code> and <code>configure()</code> methods as an <code>Element</code> object.</p>
<p>The <code>Element</code> type (from the <code>org.apache.felix.ipojo.metadata package</code>), coupled with the <code>Attribute</code> type, is used to retrieve the structure and the content of the component configuration. The <code>Element</code> parameter, passed to the initialization and configuration methods, represents the root of the component type description (i.e. the root of the tree is the <code>component</code> tag).</p>
<p>Several methods allows to browse the entire configuration from the root <code>Element</code> :</p>
<ul>
<li>The <code>getElement()</code> methods let you access the content of an <code>Element</code> (i.e. the children elements)</li>
<li>The <code>getAttribute()</code> methods allows you to access the attributes of an <code>Element</code>.</li>
<li>The <code>containsElement()</code> and <code>containsAttribute()</code> methods test the presence of a child-element or an attribute in an <code>Element</code>.</li>
</ul>
<p><em>Note :</em> As described in the <a href="#description">description</a> section, a name and a namespace are associated to each handler. To safely retrieve the configuration of this handler from the component metadata, you can take inspiration from the following snippet (the <code>componentMetadata</code> variable is the component root <code>Element</code> passed to the <code>initializeComponentFactory()</code> and <code>configure()</code> methods) :</p>
<div class="codehilite"><pre><span class="n">Element</span><span class="o">[]</span> <span class="n">log_elements</span> <span class="o">=</span> <span class="n">metadata</span><span class="o">.</span><span class="na">getElements</span><span class="o">(</span><span class="s">&quot;log&quot;</span><span class="o">,</span> <span class="n">NAMESPACE</span><span class="o">);</span>
</pre></div>
<p>For example, the log handler provided in the archive file has the following configure method: </p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * Parses the component&#39;s metadata to retrieve the log level in which we log messages.</span>
<span class="cm"> *</span>
<span class="cm"> * @param metadata component&#39;s metadata</span>
<span class="cm"> * @param configuration instance configuration (unused in this example)</span>
<span class="cm"> * @throws ConfigurationException the configuration is inconsistent</span>
<span class="cm"> */</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">configure</span><span class="o">(</span><span class="n">Element</span> <span class="n">metadata</span><span class="o">,</span> <span class="n">Dictionary</span> <span class="n">configuration</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">ConfigurationException</span> <span class="o">{</span>
<span class="c1">// First parse the metadata to check if the log handler logLevel</span>
<span class="c1">// Get all Namespace:log element from the metadata</span>
<span class="n">Element</span><span class="o">[]</span> <span class="n">log_elements</span> <span class="o">=</span> <span class="n">metadata</span><span class="o">.</span><span class="na">getElements</span><span class="o">(</span><span class="s">&quot;log&quot;</span><span class="o">,</span> <span class="n">NAMESPACE</span><span class="o">);</span>
<span class="c1">// If an element match, parse the logLevel attribute of the first found element</span>
<span class="k">if</span> <span class="o">(</span><span class="n">log_elements</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">containsAttribute</span><span class="o">(</span><span class="s">&quot;level&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">l</span> <span class="o">=</span> <span class="n">log_elements</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">getAttribute</span><span class="o">(</span><span class="s">&quot;level&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">l</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="s">&quot;info&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">logLevel</span> <span class="o">=</span> <span class="n">LogService</span><span class="o">.</span><span class="na">LOG_INFO</span><span class="o">;</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">l</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="s">&quot;error&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">logLevel</span> <span class="o">=</span> <span class="n">LogService</span><span class="o">.</span><span class="na">LOG_ERROR</span><span class="o">;</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">l</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="s">&quot;warning&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">logLevel</span> <span class="o">=</span> <span class="n">LogService</span><span class="o">.</span><span class="na">LOG_WARNING</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="n">instanceManager</span> <span class="o">=</span> <span class="n">getInstanceManager</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<p>You can also access instance configuration (properties defined in the <code>instance</code> tag). The instance properties are directly passed, as a <code>Dictionary,</code> to the <code>configure()</code> method. With these properties, you can easily allow instances to override some component fixed configuration. The property handler given in the archive file extract the location of the loaded properties file from the instance configuration:</p>
<div class="codehilite"><pre><span class="c1">// Look if the instance overrides file location :</span>
<span class="n">String</span> <span class="n">instanceFile</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">configuration</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">&quot;properties.file&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">instanceFile</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="n">m_file</span> <span class="o">=</span> <span class="n">instanceFile</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<h3 id="interacting-with-the-pojo">Interacting with the POJO<a class="headerlink" href="#interacting-with-the-pojo" title="Permanent link">&para;</a></h3>
<p>One of the most interesting features of an handler is the ability to interact with the component's POJO. Indeed, you can intercept method calls and returns, inject values in the POJO's fields...</p>
<p>The <code>getPojoMetadata()</code> method of the PrimitiveHandler class lets you access the structure of the POJO (represented by the <code>PojoMetadata</code> type) without having to use (slow) reflection. It allows you to list all fields and methods of the POJO, and get informations about implemented interfaces and the super-class. The <code>PojoMetadata</code> class implements the following operations :</p>
<ul>
<li>The <code>getInterfaces()</code> method returns the list of implemented interfaces, while the <code>isInterfaceImplemented()</code> methods test if a given interface is implemented by the POJO.</li>
<li>The <code>getSuperClass()</code> method returns the name of the class extended by the POJO (or <code>null</code> instead of <code>java.lang.Object</code>).</li>
<li>The <code>getField()</code> methods lets you access the fields of the POJO. The returned object is a <code>FieldMetadata</code> that provides information about a particular field inside the POJO.</li>
<li>The <code>getMethod()</code> methods lets you access the methods of the POJO. The returned object is a <code>MethodMetadata</code> that provides information about a particular method in the POJO.</li>
</ul>
<p>Once you've retrieved informations about the POJO structure, you can interact with it, via the <code>InstanceManager</code>, accessible in your handler by the <code>getInstanceManager()</code> method. It allows you to register interceptors, that are called before and after POJO method calls or field accesses.</p>
<p>The property handler is registering field interceptors on injected properties:</p>
<div class="codehilite"><pre><span class="c1">//First get Pojo Metadata metadata :</span>
<span class="n">PojoMetadata</span> <span class="n">pojoMeta</span> <span class="o">=</span> <span class="n">getPojoMetadata</span><span class="o">();</span>
<span class="n">Enumeration</span> <span class="n">e</span> <span class="o">=</span> <span class="n">m_properties</span><span class="o">.</span><span class="na">keys</span><span class="o">();</span>
<span class="k">while</span> <span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">hasMoreElements</span><span class="o">())</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">field</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">e</span><span class="o">.</span><span class="na">nextElement</span><span class="o">();</span>
<span class="n">FieldMetadata</span> <span class="n">fm</span> <span class="o">=</span> <span class="n">pojoMeta</span><span class="o">.</span><span class="na">getField</span><span class="o">(</span><span class="n">field</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">fm</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// The field does not exist</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;The field &quot;</span> <span class="o">+</span> <span class="n">field</span> <span class="o">+</span> <span class="s">&quot; is declared in the properties file but does not exist in the pojo&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">// Then check that the field is a String field</span>
<span class="k">if</span> <span class="o">(!</span><span class="n">fm</span><span class="o">.</span><span class="na">getFieldType</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">()))</span> <span class="o">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;The field &quot;</span> <span class="o">+</span> <span class="n">field</span> <span class="o">+</span> <span class="s">&quot; exists in the pojo, but is not a String&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">// All checks are ok, register the interceptor.</span>
<span class="n">getInstanceManager</span><span class="o">().</span><span class="na">register</span><span class="o">(</span><span class="n">fm</span><span class="o">,</span> <span class="k">this</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<div class="alert alert-info">
The InstanceManager manages the component instance attached to your handler instance. Thus, it can't be available in the <code>initializeComponentFactory()</code> because this method is run before the creation of any component instance.
</div>
<p>You need to implement some of the following methods to intercept fields accesses :</p>
<ul>
<li>The <code>void onSet(Object pojo, String fieldName, Object value)</code> method: This method is called each time a field of the POJO is assigned. The first parameter is the instance of the concerned POJO, the second is the name of the accessed field and the third is the value assigned to the POJO's field. If the field type is a primitive type, this method receives the boxed object.</li>
<li>The <code>Object onGet(Object pojo, String fieldName, Object value)</code> method : This method is called each time a field of the POJO is read. The first parameter is the instance of the concerned POJO, the second is the name of the accessed field and the third is the actual value of the POJO's field. If the field type is a primitive type, this method receives the boxed object. The returned object is the value the intercepted read process will return. It's the standard way to inject a value in the field : returning a specific object whatever the field really contains.</li>
</ul>
<p>The property handler contains the following <code>onGetz and</code>onSet` methods:</p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * This method is called at each time the pojo &#39;get&#39; a listened field. The method return the stored value.</span>
<span class="cm"> * @param pojo : pojo object getting the field</span>
<span class="cm"> * @param field : field name.</span>
<span class="cm"> * @param o : previous value.</span>
<span class="cm"> * @return the stored value.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">Object</span> <span class="nf">onGet</span><span class="o">(</span><span class="n">Object</span> <span class="n">pojo</span><span class="o">,</span> <span class="n">String</span> <span class="n">field</span><span class="o">,</span> <span class="n">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// When the pojo requires a value for a managed field, this method is invoked.</span>
<span class="c1">// So, we have just to return the stored value.</span>
<span class="k">return</span> <span class="n">m_properties</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">field</span><span class="o">);</span>
<span class="o">}</span>
<span class="cm">/**</span>
<span class="cm"> * This method is called at each time the pojo &#39;set&#39; a listened field. This method updates the local properties.</span>
<span class="cm"> * @param pojo : pojo object setting the field</span>
<span class="cm"> * @param field : field name</span>
<span class="cm"> * @param newvalue : new value</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onSet</span><span class="o">(</span><span class="n">Object</span> <span class="n">pojo</span><span class="o">,</span> <span class="n">String</span> <span class="n">field</span><span class="o">,</span> <span class="n">Object</span> <span class="n">newvalue</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// When the pojo set a value to a managed field, this method is invoked.</span>
<span class="c1">// So, we update the stored value.</span>
<span class="n">m_properties</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">field</span><span class="o">,</span> <span class="n">newvalue</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<p>You need to implements some of the following methods to intercept methods accesses. When these methods are called, the first parameter is the POJO's instance on which the intercepted method is called and the second parameter contains the descriptor of the called method.</p>
<ul>
<li>The <code>void onEntry(Object pojo, Member method, Object[] args)</code> method: This method is called before the execution of an intercepted method. The third parameter is the list of parameters with which the method have been called. The method is executed just after the execution of the <code>onEntry()</code> callback.</li>
<li>The <code>void onExit(Object pojo, Member method, Object returnedObj)</code> method: This method is called right after the successful execution of an intercepted method. The third parameter is the value returned by the method (or <code>null</code> if the method return type is <code>void</code>). This value must not be modified.</li>
<li>The <code>void onError(Object pojo, Member method, Throwable throwable)</code> method: This method is called right after the unexpected return of an intercepted method (i.e. when an uncaught exception occurred). The third parameter is the thrown object that caused the method termination.</li>
<li>The <code>void onFinally(Object pojo, Member method)</code> method: This method is called after the termination of an intercepted method (expected or not), after the call of the <code>onExit()</code> or <code>onError()</code> callback.</li>
</ul>
<div class="alert alert-warning">
The <code>InstanceManager</code> has to know your handler wants to intercept fields or methods access, otherwise the implemented callbacks won't be called. Thus you need to register each field and method you want to intercept, so the <code>InstanceManager</code> will call the appropriated callbacks when the specified field or method is accessed :
<pre>
getInstanceManager().register(anInterestingFieldMetadata, this);
...
getInstanceManager().register(anInterestingMethodMetadata, this);
...
</pre>
</div>
<div class="alert alert-info">
The <code>PrimitiveHandler</code> abstract class implements the <code>FieldInterceptor</code> and <code>MethodInterceptor</code> interfaces, which declares the methods described just above. You can create your own interceptor class (implementing one or both of these interfaces) and give it to the <code>InstanceManager</code> register method instead of the handler object itself.
</div>
<h3 id="using-your-handler">Using your handler<a class="headerlink" href="#using-your-handler" title="Permanent link">&para;</a></h3>
<p>Once your handler has been declared, you can use it in iPOJO components. To do so, you first have to be bound to your handler's namespace (using standard XML namespace declaration). Then you can configure the handler in your components type description. An example of bundle's <code>metadata.xml</code> declaring components using the handler is shown hereafter :</p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo</span> <span class="na">xmlns:your-shortcut=</span><span class="s">&quot;the.namespace.of.your.handler&quot;</span><span class="nt">&gt;</span>
...
<span class="nt">&lt;component</span> <span class="na">className=</span><span class="s">&quot;your.component.class&quot;</span><span class="nt">&gt;</span>
...
<span class="nt">&lt;your-shortcut:HandlerName</span> <span class="na">param1=</span><span class="s">&quot;value1&quot;</span> <span class="err">...</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> Configuration of your handler for </span>
<span class="c"> this component type</span>
<span class="c"> --&gt;</span>
<span class="nt">&lt;/your-shortcut:HandlerName&gt;</span>
...
<span class="nt">&lt;/component&gt;</span>
...
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<p>Obviously, you probably want to use annotations. You just have to provide the annotation classes: <code>handler_namespace.handler_element</code>. For instance, the log handler provides the <code>org.apache.felix.ipojo.log.handler.Log</code> annotation:</p>
<div class="codehilite"><pre><span class="kn">package</span> <span class="n">org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">felix</span><span class="o">.</span><span class="na">ipojo</span><span class="o">.</span><span class="na">log</span><span class="o">.</span><span class="na">handler</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * The annotation used to configure the LogHandler.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">Log</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">enum</span> <span class="n">Level</span> <span class="o">{</span>
<span class="n">INFO</span><span class="o">,</span> <span class="n">ERROR</span><span class="o">,</span> <span class="n">WARNING</span>
<span class="o">}</span>
<span class="cm">/**</span>
<span class="cm"> * @return the log level</span>
<span class="cm"> */</span>
<span class="n">Level</span> <span class="nf">level</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<p>The remainder of this document describes two examples of handlers:
<em> A log handler logging messages in the OSGi Log Service
</em> A properties handler reading a property files to configure POJO field</p>
<h2 id="log-handler-example">Log Handler example<a class="headerlink" href="#log-handler-example" title="Permanent link">&para;</a></h2>
<p>This section describes how to create a simple handler. This handler logs a message in the <em>OSGi Log Service</em> (if present) when the component instance state changes.</p>
<h3 id="handler-metadata">Handler metadata<a class="headerlink" href="#handler-metadata" title="Permanent link">&para;</a></h3>
<p>The handler namespace is <code>org.apache.felix.ipojo.log.handler.LogHandler</code>. It is also the name of the handler implementation class. You can note that the handler has an optional dependency on a OSGi log service.</p>
<div class="codehilite"><pre><span class="c1">// Declare a handler.</span>
<span class="nd">@Handler</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;Log&quot;</span><span class="o">,</span> <span class="n">namespace</span> <span class="o">=</span> <span class="n">LogHandler</span><span class="o">.</span><span class="na">NAMESPACE</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">LogHandler</span> <span class="kd">extends</span> <span class="n">PrimitiveHandler</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">NAMESPACE</span> <span class="o">=</span> <span class="s">&quot;org.apache.felix.ipojo.log.handler&quot;</span><span class="o">;</span>
<span class="c1">// Handlers are iPOJO components, so can use service dependencies</span>
<span class="nd">@Requires</span><span class="o">(</span><span class="n">optional</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="n">nullable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="n">LogService</span> <span class="n">log</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">InstanceManager</span> <span class="n">instanceManager</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">logLevel</span><span class="o">;</span>
<span class="c1">//...</span>
</pre></div>
<h3 id="handler-implementation">Handler implementation<a class="headerlink" href="#handler-implementation" title="Permanent link">&para;</a></h3>
<p>The handler needs to override following methods:
<em> <code>configure</code> : to parse the metadata and load the properties file
</em> <code>stateChanged</code> : to log messages when the instance state changes.</p>
<h4 id="loghandler-class">LogHandler class<a class="headerlink" href="#loghandler-class" title="Permanent link">&para;</a></h4>
<p>The handler is implemented inside the <code>LogHandler</code> class in the <code>org.apache.felix.ipojo.handler.log</code> package. This class extends the <code>org.apache.felix.ipojo.PrimitiveHandler</code> class.
The handler needs to be notified when component instances becomes valid or invalid, thus it implements the <code>InstanceStateListener</code> interface.</p>
<h4 id="configure-method">Configure Method<a class="headerlink" href="#configure-method" title="Permanent link">&para;</a></h4>
<p>This method reads the component description and configures the handler. Then, the handler registers itself to the instance manager to be informed of the component's validity changes.</p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * Parses the component&#39;s metadata to retrieve the log level in which we log messages.</span>
<span class="cm"> *</span>
<span class="cm"> * @param metadata component&#39;s metadata</span>
<span class="cm"> * @param configuration instance configuration (unused in this example)</span>
<span class="cm"> * @throws ConfigurationException the configuration is inconsistent</span>
<span class="cm"> */</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">configure</span><span class="o">(</span><span class="n">Element</span> <span class="n">metadata</span><span class="o">,</span> <span class="n">Dictionary</span> <span class="n">configuration</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">ConfigurationException</span> <span class="o">{</span>
<span class="c1">// First parse the metadata to check if the log handler logLevel</span>
<span class="c1">// Get all Namespace:log element from the metadata</span>
<span class="n">Element</span><span class="o">[]</span> <span class="n">log_elements</span> <span class="o">=</span> <span class="n">metadata</span><span class="o">.</span><span class="na">getElements</span><span class="o">(</span><span class="s">&quot;log&quot;</span><span class="o">,</span> <span class="n">NAMESPACE</span><span class="o">);</span>
<span class="c1">// If an element match, parse the logLevel attribute of the first found element</span>
<span class="k">if</span> <span class="o">(</span><span class="n">log_elements</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">containsAttribute</span><span class="o">(</span><span class="s">&quot;level&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">l</span> <span class="o">=</span> <span class="n">log_elements</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">getAttribute</span><span class="o">(</span><span class="s">&quot;level&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">l</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="s">&quot;info&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">logLevel</span> <span class="o">=</span> <span class="n">LogService</span><span class="o">.</span><span class="na">LOG_INFO</span><span class="o">;</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">l</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="s">&quot;error&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">logLevel</span> <span class="o">=</span> <span class="n">LogService</span><span class="o">.</span><span class="na">LOG_ERROR</span><span class="o">;</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">l</span><span class="o">.</span><span class="na">equalsIgnoreCase</span><span class="o">(</span><span class="s">&quot;warning&quot;</span><span class="o">))</span> <span class="o">{</span>
<span class="n">logLevel</span> <span class="o">=</span> <span class="n">LogService</span><span class="o">.</span><span class="na">LOG_WARNING</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="n">instanceManager</span> <span class="o">=</span> <span class="n">getInstanceManager</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<h4 id="statechanged-method">StateChanged Method<a class="headerlink" href="#statechanged-method" title="Permanent link">&para;</a></h4>
<p>This method is called by the instance manager to notify that the component instance state changes. The handler needs to log a message containing the new state.</p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * Logging messages when the instance state is changing</span>
<span class="cm"> *</span>
<span class="cm"> * @param state the new state</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">stateChanged</span><span class="o">(</span><span class="kt">int</span> <span class="n">state</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">log</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">state</span> <span class="o">==</span> <span class="n">InstanceManager</span><span class="o">.</span><span class="na">VALID</span><span class="o">)</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&quot;The component instance &quot;</span> <span class="o">+</span> <span class="n">instanceManager</span><span class="o">.</span><span class="na">getInstanceName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot; becomes valid&quot;</span><span class="o">);</span>
<span class="n">log</span><span class="o">.</span><span class="na">log</span><span class="o">(</span><span class="n">logLevel</span><span class="o">,</span> <span class="s">&quot;The component instance &quot;</span> <span class="o">+</span> <span class="n">instanceManager</span><span class="o">.</span><span class="na">getInstanceName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot; becomes valid&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="k">if</span> <span class="o">(</span><span class="n">state</span> <span class="o">==</span> <span class="n">InstanceManager</span><span class="o">.</span><span class="na">INVALID</span><span class="o">)</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&quot;The component instance &quot;</span> <span class="o">+</span> <span class="n">instanceManager</span><span class="o">.</span><span class="na">getInstanceName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot; becomes invalid&quot;</span><span class="o">);</span>
<span class="n">log</span><span class="o">.</span><span class="na">log</span><span class="o">(</span><span class="n">logLevel</span><span class="o">,</span> <span class="s">&quot;The component instance &quot;</span> <span class="o">+</span> <span class="n">instanceManager</span><span class="o">.</span><span class="na">getInstanceName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot; becomes invalid&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h3 id="start-and-stop">Start and Stop<a class="headerlink" href="#start-and-stop" title="Permanent link">&para;</a></h3>
<p>The handler also contains two methods called by the instance manager when the underlying instance starts and stops.</p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * The instance is starting.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">log</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="n">log</span><span class="o">.</span><span class="na">log</span><span class="o">(</span><span class="n">logLevel</span><span class="o">,</span> <span class="s">&quot;The component instance &quot;</span> <span class="o">+</span> <span class="n">instanceManager</span><span class="o">.</span><span class="na">getInstanceName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot; is starting&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="cm">/**</span>
<span class="cm"> * The instance is stopping.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">stop</span><span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">log</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="n">log</span><span class="o">.</span><span class="na">log</span><span class="o">(</span><span class="n">logLevel</span><span class="o">,</span> <span class="s">&quot;The component instance &quot;</span> <span class="o">+</span> <span class="n">instanceManager</span><span class="o">.</span><span class="na">getInstanceName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot; is stopping&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h2 id="handler-packaging">Handler packaging<a class="headerlink" href="#handler-packaging" title="Permanent link">&para;</a></h2>
<p>This handler needs to be packaged inside an iPOJO bundle. The bundle will import the <code>org.apache.felix.ipojo</code>, <code>org.osgi.framework</code> and <code>org.osgi.service.log</code> packages.</p>
<h3 id="handler-usage">Handler usage<a class="headerlink" href="#handler-usage" title="Permanent link">&para;</a></h3>
<p>To use this handler, a component use the <code>Log</code> annotation, with a level attribute. This level attribute's value can be <code>"error"</code>, <code>"warning"</code> or <code>"info"</code>. Here is an usage example:</p>
<div class="codehilite"><pre><span class="kn">package</span> <span class="n">org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">felix</span><span class="o">.</span><span class="na">ipojo</span><span class="o">.</span><span class="na">log</span><span class="o">.</span><span class="na">handler</span><span class="o">.</span><span class="na">example</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.annotations.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.foo.FooService</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.log.handler.Log</span><span class="o">;</span>
<span class="nd">@Component</span><span class="o">(</span><span class="n">immediate</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
<span class="nd">@Log</span><span class="o">(</span><span class="n">level</span> <span class="o">=</span> <span class="n">Log</span><span class="o">.</span><span class="na">Level</span><span class="o">.</span><span class="na">INFO</span><span class="o">)</span> <span class="c1">// We configure the handler.</span>
<span class="nd">@Instantiate</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;my.simple.consumer&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SimpleComponent</span> <span class="o">{</span>
<span class="nd">@Requires</span>
<span class="n">FooService</span> <span class="n">fs</span><span class="o">;</span>
<span class="nd">@Validate</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">starting</span><span class="o">()</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&quot;Starting...&quot;</span><span class="o">);</span>
<span class="n">fs</span><span class="o">.</span><span class="na">foo</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Invalidate</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">stopping</span><span class="o">()</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&quot;Stopping...&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h3 id="playing-with-the-handler">Playing with the handler<a class="headerlink" href="#playing-with-the-handler" title="Permanent link">&para;</a></h3>
<p>The archive contains a project named <code>Log-Handler-In-Felix</code>, which once built, provides a Felix framework with all the bundles deployed.</p>
<p>Unzip the archive, and build the whole project using Maven: <code>mvn clean install</code>. It builds the log handler and the property handler. Then navigate to the felix-framework-VERSION directory:</p>
<div class="codehilite"><pre>mvn clean install
<span class="c">#...</span>
<span class="nb">cd </span>Log-Handler-In-Felix/target/felix-framework-4.2.1/
java -jar bin/felix.jar
</pre></div>
<p>Once you have launched Felix, you get the Gogo Shell prompt:</p>
<div class="codehilite"><pre>Starting...
Foo
The component instance my.simple.consumer becomes valid
____________________________
Welcome to Apache Felix Gogo
g! lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle <span class="o">(</span>4.2.1<span class="o">)</span>
1|Active | 1|Apache Felix Bundle Repository <span class="o">(</span>1.6.6<span class="o">)</span>
2|Active | 1|Apache Felix Gogo Command <span class="o">(</span>0.12.0<span class="o">)</span>
3|Active | 1|Apache Felix Gogo Runtime <span class="o">(</span>0.10.0<span class="o">)</span>
4|Active | 1|Apache Felix Gogo Shell <span class="o">(</span>0.10.0<span class="o">)</span>
5|Active | 1|Apache Felix iPOJO <span class="o">(</span>1.8.6<span class="o">)</span>
6|Active | 1|Apache Felix iPOJO Gogo Command <span class="o">(</span>1.0.1<span class="o">)</span>
7|Active | 1|iPOJO Log Handler Consumer <span class="o">(</span>1.9.0.SNAPSHOT<span class="o">)</span>
8|Active | 1|iPOJO Foo Service <span class="o">(</span>1.9.0.SNAPSHOT<span class="o">)</span>
9|Active | 1|iPOJO Log Handler <span class="o">(</span>1.9.0.SNAPSHOT<span class="o">)</span>
10|Active | 1|Apache Felix Log Service <span class="o">(</span>1.0.1<span class="o">)</span>
g!
</pre></div>
<p>You can already see some of the messages printed by the handler (<code>The component instance my.simple.consumer becomes valid</code>). To see more message, stop and start the Foo Service bundle:</p>
<div class="codehilite"><pre>g! stop 8
The component instance my.simple.consumer becomes invalid
Stopping...
g! start 8
g! Starting...
Foo
The component instance my.simple.consumer becomes valid
</pre></div>
<p>By stopping the Foo service bundle, you withdrew the foo service from the service registry making our component invalid (and unhappy). The handler is notified of the new state and logs a message. When the bundle restarts, the service is republished. So the instance becomes valid again. The handler is notified and logs another message.</p>
<h2 id="properties-handler-example">Properties Handler example<a class="headerlink" href="#properties-handler-example" title="Permanent link">&para;</a></h2>
<p>This section presents a second handler. This handler loads a property file containing field name and initial value. Then it injects and maintains these values inside POJO fields. In this example, only String values are managed.</p>
<p>This handler is always valid, so do not participate to the component instance lifecycle. Moreover, the handler does not need to be notified when the component instance state changed. But, it need to be notified when POJO fields need a value or change their value.</p>
<h3 id="handler-implementation_1">Handler implementation<a class="headerlink" href="#handler-implementation_1" title="Permanent link">&para;</a></h3>
<p>The handler needs to override following methods:</p>
<ul>
<li><code>configure</code> : to parse the metadata and load the properties file </li>
<li><code>stop</code> : to store the properties </li>
<li><code>onGet</code> : to inject a values inside a field </li>
<li><code>onSet</code> : to obtain the new field value </li>
</ul>
<h4 id="propertieshandler-class">PropertiesHandler class<a class="headerlink" href="#propertieshandler-class" title="Permanent link">&para;</a></h4>
<p>The handler is implemented by the <code>PropertiesHandler</code> class present in the <code>org.apache.felix.ipojo.properties.handler</code> package. The class has several fields:</p>
<ul>
<li>The properties to maintain (<code>m_properties</code>) </li>
<li>The properties file name (<code>m_file</code>) </li>
</ul>
<p><em>Note:</em> the file name is the absolute path on the local machine of the file.</p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * This handler load a properties file containing property value.</span>
<span class="cm"> * The handler injects this values inside fields. When stopped the handler stores updated value inside the file. The</span>
<span class="cm"> * properties file contains &lt;pre&gt;field-name : field-value&lt;/pre&gt; (field-value are strings)</span>
<span class="cm"> *</span>
<span class="cm"> * Instances can override file locations by setting the {@literal properties.file} property.</span>
<span class="cm"> *</span>
<span class="cm"> * @author &lt;a href=&quot;mailto:dev@felix.apache.org&quot;&gt;Felix Project Team&lt;/a&gt;</span>
<span class="cm"> */</span>
<span class="nd">@Handler</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">&quot;properties&quot;</span><span class="o">,</span> <span class="n">namespace</span> <span class="o">=</span> <span class="n">PropertiesHandler</span><span class="o">.</span><span class="na">NAMESPACE</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">PropertiesHandler</span> <span class="kd">extends</span> <span class="n">PrimitiveHandler</span> <span class="o">{</span>
<span class="cm">/**</span>
<span class="cm"> * The Handler namespace.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">NAMESPACE</span> <span class="o">=</span> <span class="s">&quot;org.apache.felix.ipojo.handler.properties&quot;</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * The loaded properties.</span>
<span class="cm"> */</span>
<span class="kd">private</span> <span class="n">Properties</span> <span class="n">m_properties</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Properties</span><span class="o">();</span>
<span class="cm">/**</span>
<span class="cm"> * The properties file location, configured in the component&#39;s metadata.</span>
<span class="cm"> */</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">m_file</span><span class="o">;</span>
</pre></div>
<h4 id="configure-method_1">Configure Method<a class="headerlink" href="#configure-method_1" title="Permanent link">&para;</a></h4>
<p>This method begins by parsing the component type metadata. The handler needs a properties element from its namespace. According to the result, the configure method can return immediately or parse the file attribute (to get the properties file path). Then, it builds a field list (String array) to register to field notification. By registering with a field array, the handler is going to be notified of field access.</p>
<div class="codehilite"><pre><span class="cm">/**</span>
<span class="cm"> * This method is the first to be invoked.</span>
<span class="cm"> * This method aims to configure the handler. It receives the component type metadata and the instance</span>
<span class="cm"> * configuration. The method parses given metadata and registers fields to inject.</span>
<span class="cm"> *</span>
<span class="cm"> * Step 3 : when the instance configuration contains the properties.file property, it overrides the properties file location.</span>
<span class="cm"> *</span>
<span class="cm"> * @param metadata : component type metadata</span>
<span class="cm"> * @param configuration : instance description</span>
<span class="cm"> * @throws ConfigurationException : the configuration of the handler has failed.</span>
<span class="cm"> */</span>
<span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">&quot;unchecked&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">configure</span><span class="o">(</span><span class="n">Element</span> <span class="n">metadata</span><span class="o">,</span> <span class="n">Dictionary</span> <span class="n">configuration</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">ConfigurationException</span> <span class="o">{</span>
<span class="c1">// Get all elements to configure the handler</span>
<span class="n">Element</span><span class="o">[]</span> <span class="n">elem</span> <span class="o">=</span> <span class="n">metadata</span><span class="o">.</span><span class="na">getElements</span><span class="o">(</span><span class="s">&quot;properties&quot;</span><span class="o">,</span> <span class="n">NAMESPACE</span><span class="o">);</span>
<span class="k">switch</span> <span class="o">(</span><span class="n">elem</span><span class="o">.</span><span class="na">length</span><span class="o">)</span> <span class="o">{</span>
<span class="k">case</span> <span class="mi">0</span><span class="o">:</span>
<span class="c1">// No matching element in metadata, throw a configuration error.</span>
<span class="c1">// It actually happen only if you force the handler to be plugged.</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;No properties found&quot;</span><span class="o">);</span>
<span class="k">case</span> <span class="mi">1</span><span class="o">:</span>
<span class="c1">// One &#39;properties&#39; found, get attributes.</span>
<span class="n">m_file</span> <span class="o">=</span> <span class="n">elem</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">getAttribute</span><span class="o">(</span><span class="s">&quot;file&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">m_file</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// if file is null, throw a configuration error.</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;Malformed properties element : file attribute must be set&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="c1">// To simplify we handle only one properties element.</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;Only one properties element is supported&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">// Look if the instance overrides file location :</span>
<span class="n">String</span> <span class="n">instanceFile</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">configuration</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">&quot;properties.file&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">instanceFile</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="n">m_file</span> <span class="o">=</span> <span class="n">instanceFile</span><span class="o">;</span>
<span class="o">}</span>
<span class="c1">// Load properties</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">loadProperties</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;Error when reading the &quot;</span> <span class="o">+</span> <span class="n">m_file</span> <span class="o">+</span> <span class="s">&quot; file : &quot;</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="o">}</span>
<span class="c1">// Register fields</span>
<span class="c1">// By convention, properties file entry are field name, so look for each property to get field list.</span>
<span class="c1">//First get Pojo Metadata metadata :</span>
<span class="n">PojoMetadata</span> <span class="n">pojoMeta</span> <span class="o">=</span> <span class="n">getPojoMetadata</span><span class="o">();</span>
<span class="n">Enumeration</span> <span class="n">e</span> <span class="o">=</span> <span class="n">m_properties</span><span class="o">.</span><span class="na">keys</span><span class="o">();</span>
<span class="k">while</span> <span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">hasMoreElements</span><span class="o">())</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">field</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">e</span><span class="o">.</span><span class="na">nextElement</span><span class="o">();</span>
<span class="n">FieldMetadata</span> <span class="n">fm</span> <span class="o">=</span> <span class="n">pojoMeta</span><span class="o">.</span><span class="na">getField</span><span class="o">(</span><span class="n">field</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">fm</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// The field does not exist</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;The field &quot;</span> <span class="o">+</span> <span class="n">field</span> <span class="o">+</span> <span class="s">&quot; is declared in the properties file but does not exist in the pojo&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">// Then check that the field is a String field</span>
<span class="k">if</span> <span class="o">(!</span><span class="n">fm</span><span class="o">.</span><span class="na">getFieldType</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">()))</span> <span class="o">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConfigurationException</span><span class="o">(</span><span class="s">&quot;The field &quot;</span> <span class="o">+</span> <span class="n">field</span> <span class="o">+</span> <span class="s">&quot; exists in the pojo, but is not a String&quot;</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">// All checks are ok, register the interceptor.</span>
<span class="n">getInstanceManager</span><span class="o">().</span><span class="na">register</span><span class="o">(</span><span class="n">fm</span><span class="o">,</span> <span class="k">this</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>Notice that the handler is using the instance configuration. So instances can set their own file location using the <code>properties.file</code> property.</p>
<h4 id="the-start-and-stop-methods">The start and stop methods<a class="headerlink" href="#the-start-and-stop-methods" title="Permanent link">&para;</a></h4>
<p>The start method does nothing, but needs to be implemented.</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">()</span> <span class="o">{}</span>
</pre></div>
<p>The stop method stores properties inside the properties file.</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">stop</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">saveProperties</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// Log an error message by using the iPOJO logger </span>
<span class="n">error</span><span class="o">(</span><span class="s">&quot;Cannot read the file : &quot;</span> <span class="o">+</span> <span class="n">m_file</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
<span class="o">}</span>
<span class="n">m_properties</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<h4 id="onget-and-onset-methods">onGet and onSet methods<a class="headerlink" href="#onget-and-onset-methods" title="Permanent link">&para;</a></h4>
<p>The onGet method is called when the POJO need a field value. When called, the method needs to return the stored value.The onSet method is called when the POJO modifies a field value. If the new value if null, the handler will remove this properties from the property list.</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="n">Object</span> <span class="nf">onGet</span><span class="o">(</span><span class="n">Object</span> <span class="n">pojo</span><span class="o">,</span> <span class="n">String</span> <span class="n">field</span><span class="o">,</span> <span class="n">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// When the pojo requires a value for a managed field,</span>
<span class="c1">// this method is invoked. </span>
<span class="c1">// So, we have just to return the stored value. </span>
<span class="k">return</span> <span class="n">m_properties</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">field</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onSet</span><span class="o">(</span><span class="n">Object</span> <span class="n">pojo</span><span class="o">,</span> <span class="n">String</span> <span class="n">field</span><span class="o">,</span> <span class="n">Object</span> <span class="n">newvalue</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// When the pojo set a value to a managed field, </span>
<span class="c1">// this method is invoked. </span>
<span class="c1">// So, we update the stored value. </span>
<span class="n">m_properties</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">field</span><span class="o">,</span> <span class="n">newvalue</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<h3 id="creating-the-annotation">Creating the annotation<a class="headerlink" href="#creating-the-annotation" title="Permanent link">&para;</a></h3>
<p>The handler provides an annotation to ease its use:</p>
<div class="codehilite"><pre><span class="kn">package</span> <span class="n">org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">felix</span><span class="o">.</span><span class="na">ipojo</span><span class="o">.</span><span class="na">handler</span><span class="o">.</span><span class="na">properties</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * The Properties annotation.</span>
<span class="cm"> * This annotation may be used in POJO class to used the Property handler.</span>
<span class="cm"> * @author &lt;a href=&quot;mailto:dev@felix.apache.org&quot;&gt;Felix Project Team&lt;/a&gt;</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">Properties</span> <span class="o">{</span>
<span class="cm">/**</span>
<span class="cm"> * Returns the property file used by the handler.</span>
<span class="cm"> */</span>
<span class="n">String</span> <span class="nf">file</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<h3 id="handler-packaging_1">Handler packaging<a class="headerlink" href="#handler-packaging_1" title="Permanent link">&para;</a></h3>
<p>This handler needs to be inside a bundle importing the <code>org.apache.felix.ipojo</code> packages and exporting the <code>org.apache.felix.ipojo.properties.handler</code> package.</p>
<h3 id="playing-with-the-handler_1">Playing with the handler<a class="headerlink" href="#playing-with-the-handler_1" title="Permanent link">&para;</a></h3>
<p>As for the log handler , the archive contains a felix distribution with all bundles deployed.</p>
<div class="codehilite"><pre><span class="nb">cd </span>Property-Handler-In-Felix/target/felix-framework-4.2.1/
java -jar bin/felix.jar
</pre></div>
<p>In Gogo you immediately see the loaded properties:</p>
<div class="codehilite"><pre>-- listing properties --
<span class="nv">property2</span><span class="o">=</span><span class="s2">&quot;bbb&quot;</span>
<span class="nv">property1</span><span class="o">=</span><span class="s2">&quot;aaa&quot;</span>
PropertiesTester is starting ...
Property 1 : <span class="s2">&quot;aaa&quot;</span>
Property 2 : <span class="s2">&quot;bbb&quot;</span>
Update properties
-- listing properties --
<span class="nv">property2</span><span class="o">=</span><span class="s2">&quot;bbb&quot;</span>
<span class="nv">property1</span><span class="o">=</span><span class="s2">&quot;aaa&quot;</span>
PropertiesTester is starting ...
Property 1 : <span class="s2">&quot;aaa&quot;</span>
Property 2 : <span class="s2">&quot;bbb&quot;</span>
Update properties
____________________________
Welcome to Apache Felix Gogo
g!
</pre></div>
<p>In this example, we have two instances of the same component type loading different properties files. The first instance loads the default properties file. The second one is configured to read another one. This configuraiton is given in the instance configuration:</p>
<div class="codehilite"><pre><span class="nt">&lt;ipojo&gt;</span>
<span class="c">&lt;!-- Declare an instance illustrating instance configuration --&gt;</span>
<span class="nt">&lt;instance</span> <span class="na">component=</span><span class="s">&quot;PropertiesTester&quot;</span>
<span class="na">name=</span><span class="s">&quot;instance-using-properties-i1&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;props.file&quot;</span>
<span class="na">value=</span><span class="s">&quot;props\properties-i1.properties&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/instance&gt;</span>
<span class="nt">&lt;/ipojo&gt;</span>
</pre></div>
<h2 id="advanced-topics">Advanced topics<a class="headerlink" href="#advanced-topics" title="Permanent link">&para;</a></h2>
<h3 id="handler-reconfiguration">Handler reconfiguration<a class="headerlink" href="#handler-reconfiguration" title="Permanent link">&para;</a></h3>
<p>iPOJO has the ability to reconfigure component instances while they are running. When instances are reconfigured, their used handler need to update their configuration (if they support such an operation).
To do so, reconfigurable handlers must override the <code>reconfigure()</code> method, which notify the concerned handlers of the new instance configuration (represented as a <code>Dictionary</code>).</p>
<p><a name="description"></a></p>
<h3 id="describing-your-handler">Describing your handler<a class="headerlink" href="#describing-your-handler" title="Permanent link">&para;</a></h3>
<p>Handlers have the possibility to describe their state, overriding the <code>getDescription()</code> method and the <code>HandlerDescription</code> class.
By default, only the handler's name and validity are displayed in component instance's description (informations displayed by the (<code>arch -instance an.instance.name</code> command). The standard way to add description to your handler is shown hereafter :</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">YourHandler</span> <span class="kd">extends</span> <span class="n">PrimitiveHandler</span> <span class="o">{</span>
<span class="o">...</span>
<span class="c1">// Method returning the handler description. </span>
<span class="kd">public</span> <span class="n">HandlerDescription</span> <span class="nf">getDescription</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">YourHandlerDescription</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">...</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">YourHandlerDescription</span> <span class="kd">extends</span> <span class="n">HandlerDescription</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nf">Description</span><span class="o">(</span><span class="n">PrimitiveHandler</span> <span class="n">h</span><span class="o">)</span> <span class="o">{</span> <span class="kd">super</span><span class="o">(</span><span class="n">h</span><span class="o">);</span> <span class="o">}</span>
<span class="c1">// Method returning the custom description of this handler. </span>
<span class="kd">public</span> <span class="n">Element</span> <span class="nf">getHandlerInfo</span><span class="o">()</span> <span class="o">{</span>
<span class="c1">// Needed to get the root description element. </span>
<span class="n">Element</span> <span class="n">elem</span> <span class="o">=</span> <span class="kd">super</span><span class="o">.</span><span class="na">getHandlerInfo</span><span class="o">();</span>
<span class="c1">// Add here attributes and sub-elements </span>
<span class="c1">// into the root description element. </span>
<span class="c1">// Example : elem.addAttribute(new Attribute(&quot;param&quot;, &quot;value&quot;)); </span>
<span class="n">Element</span> <span class="n">subElement</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Element</span><span class="o">(</span><span class="s">&quot;subElement&quot;</span><span class="o">,</span> <span class="s">&quot;&quot;</span><span class="o">);</span>
<span class="n">subElement</span><span class="o">.</span><span class="na">addAttribute</span><span class="o">(</span><span class="k">new</span> <span class="n">Attribute</span><span class="o">(</span><span class="s">&quot;subParam&quot;</span><span class="o">,</span> <span class="s">&quot;subValue&quot;</span><span class="o">));</span>
<span class="n">elem</span><span class="o">.</span><span class="na">addElement</span><span class="o">(</span><span class="n">subElement</span><span class="o">);</span>
<span class="o">...</span>
<span class="k">return</span> <span class="n">elem</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p><a name="annotations"></a></p>
<h2 id="handlers-annotations">Handler's annotations<a class="headerlink" href="#handlers-annotations" title="Permanent link">&para;</a></h2>
<p>Your handle can also provide annotations. Annotations will allows users to configure the Handler from the source code (avoiding XML edition). iPOJO supports annotation of external handlers. Indeed, it detects annotations and re-creates the <code>Element-Attribute</code> structure.
So, first, external Handler annotations <em>MUST</em> follow some principles:</p>
<ul>
<li>The annotation package must be the Handler namespace</li>
<li>The annotation name must be the Handler name</li>
<li>The package must contain either the 'ipojo' or the 'handler' word.</li>
</ul>
<p>So, when iPOJO detects the annotation, an Element is created with the annotation package as the <code>Element namespace</code> and the annotation name as the <code>Element name</code>.
Then, 'scalar' annotation attributes are mapped to Attribute. Sub-annotations (annotation attribute) are mapped to sub-elements. For example, the annotation for the property handler is:</p>
<div class="codehilite"><pre><span class="kn">package</span> <span class="n">org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">felix</span><span class="o">.</span><span class="na">ipojo</span><span class="o">.</span><span class="na">properties</span><span class="o">.</span><span class="na">handler</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.ElementType</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.Target</span><span class="o">;</span>
<span class="nd">@Target</span><span class="o">(</span><span class="n">ElementType</span><span class="o">.</span><span class="na">TYPE</span><span class="o">)</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">Properties</span> <span class="o">{</span>
<span class="n">String</span> <span class="nf">file</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<p>This annotations is put on the element, and allows setting the property file:</p>
<div class="codehilite"><pre><span class="nd">@Component</span>
<span class="nd">@Properties</span><span class="o">(</span><span class="n">file</span><span class="o">=</span><span class="s">&quot;/Users/clement/felix/properties/i1.properties&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Example</span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
</pre></div>
<p>However, your handler can also provide several annotations to represent Element and sub-elements. Your annotations can also be placed on different code elements (Type, Field, Method). In this case, to recreate the Element/Sub-Element hierarchy, iPOJO processes as following:</p>
<ul>
<li>The first annotation of a package <code>P</code> is processed by creating the root Element (component sub-element).</li>
<li>All others annotations of the package <code>P</code> are processed as sub-element of the previously created Element.</li>
</ul>
<p>For example, the following code:</p>
<div class="codehilite"><pre><span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.annotations.Component</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.handlers.jmx.Config</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.handlers.jmx.Method</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.felix.ipojo.handlers.jmx.Property</span><span class="o">;</span>
<span class="nd">@Component</span>
<span class="nd">@Config</span><span class="o">(</span><span class="n">domain</span><span class="o">=</span><span class="s">&quot;my-domain&quot;</span><span class="o">,</span> <span class="n">usesMOSGi</span><span class="o">=</span><span class="kc">false</span><span class="o">)</span> <span class="c1">// External handler annotation</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">JMXSimple</span> <span class="o">{</span>
<span class="nd">@Property</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">&quot;prop&quot;</span><span class="o">,</span> <span class="n">notification</span><span class="o">=</span><span class="kc">true</span><span class="o">,</span> <span class="n">rights</span><span class="o">=</span><span class="s">&quot;w&quot;</span><span class="o">)</span> <span class="c1">//External handler annotation</span>
<span class="n">String</span> <span class="n">m_foo</span><span class="o">;</span>
<span class="nd">@Method</span><span class="o">(</span><span class="n">description</span><span class="o">=</span><span class="s">&quot;set the foo prop&quot;</span><span class="o">)</span> <span class="c1">//External handler annotation</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setFoo</span><span class="o">(</span><span class="n">String</span> <span class="n">mes</span><span class="o">)</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&quot;Set foo to &quot;</span> <span class="o">+</span> <span class="n">mes</span><span class="o">);</span>
<span class="n">m_foo</span> <span class="o">=</span> <span class="n">mes</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@Method</span><span class="o">(</span><span class="n">description</span><span class="o">=</span><span class="s">&quot;get the foo prop&quot;</span><span class="o">)</span> <span class="c1">//External handler annotation</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getFoo</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">m_foo</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>will be translated to:</p>
<div class="codehilite"><pre>component <span class="o">{</span>
<span class="nv">$classname</span><span class="o">=</span><span class="s2">&quot;org.apache.felix.ipojo.test.scenarios.component.jmx.JMXSimple&quot;</span>
<span class="nv">$public</span><span class="o">=</span><span class="s2">&quot;true&quot;</span> <span class="nv">$name</span><span class="o">=</span><span class="s2">&quot;org.apache.felix.ipojo.test.scenarios.component.jmx.JMXSimple&quot;</span>
org.apache.felix.ipojo.handlers.jmx:config <span class="o">{</span>
<span class="nv">$usesmosgi</span><span class="o">=</span><span class="s2">&quot;false&quot;</span> <span class="nv">$domain</span><span class="o">=</span><span class="s2">&quot;my-domain&quot;</span>
org.apache.felix.ipojo.handlers.jmx:property <span class="o">{</span>
<span class="nv">$rights</span><span class="o">=</span><span class="s2">&quot;w&quot;</span> <span class="nv">$notification</span><span class="o">=</span><span class="s2">&quot;true&quot;</span> <span class="nv">$field</span><span class="o">=</span><span class="s2">&quot;m_foo&quot;</span> <span class="nv">$name</span><span class="o">=</span><span class="s2">&quot;prop&quot;</span> <span class="o">}</span>
org.apache.felix.ipojo.handlers.jmx:method <span class="o">{</span>
<span class="nv">$description</span><span class="o">=</span><span class="s2">&quot;set the foo prop&quot;</span> <span class="nv">$method</span><span class="o">=</span><span class="s2">&quot;setFoo&quot;</span> <span class="o">}</span>
org.apache.felix.ipojo.handlers.jmx:method <span class="o">{</span>
<span class="nv">$description</span><span class="o">=</span><span class="s2">&quot;get the foo prop&quot;</span> <span class="nv">$method</span><span class="o">=</span><span class="s2">&quot;getFoo&quot;</span> <span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p><em>Note:</em> To customize this hierarchy, you can also use the <code>id/parent</code> annotation attributse. The id attribute is used to refer to an Element. An annotation with a <code>parent</code> (targeting an <code>id</code>) attribute will be processed as a sub-element of the Element identified by the given <code>id</code>.</p>
<p><a name="schemas"></a></p>
<h2 id="handlers-xsd">Handler's XSD<a class="headerlink" href="#handlers-xsd" title="Permanent link">&para;</a></h2>
<p>Coming soon...</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">&para;</a></h2>
<p>In this document, we present how-to develop handler for your components. We describe two small examples : a log handler and a properties handler. These handlers are plugged on (primitive) instance. However, it is possible to extends <code>CompositeHandler</code> too to customize the composition model.</p>
<p>If you develop handler and you want to share it, feel free to contact us by sending a mail on the Felix mailing list.</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>