| <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html><head> |
| |
| |
| |
| <title>Apache Felix - Service Requirement Handler</title> |
| <link rel="stylesheet" href="service-requirement-handler_files/site.css" type="text/css" media="all"> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| </head><body> |
| <div class="title"><div class="logo"><a href="http://felix.apache.org/site/index.html"><img alt="Apache Felix" src="service-requirement-handler_files/logo.png" border="0"></a></div><div class="header"><a href="http://www.apache.org/"><img alt="Apache" src="service-requirement-handler_files/apache.png" border="0"></a></div></div> |
| <div class="menu"> |
| <ul> |
| <li><a href="http://felix.apache.org/site/news.html" title="news">news</a></li> |
| <li><a href="http://felix.apache.org/site/license.html" title="license">license</a></li> |
| <li><span class="nobr"><a href="http://felix.apache.org/site/downloads.cgi" title="Visit page outside Confluence" rel="nofollow">downloads<sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span></li> |
| <li><a href="http://felix.apache.org/site/documentation.html" title="documentation">documentation</a></li> |
| <li><a href="http://felix.apache.org/site/mailinglists.html" title="mailinglists">mailing lists</a></li> |
| <li><a href="http://felix.apache.org/site/contributing.html" title="Contributing">contributing</a></li> |
| <li><span class="nobr"><a href="http://www.apache.org/" title="Visit page outside Confluence" rel="nofollow">asf<sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span></li> |
| <li><span class="nobr"><a href="http://www.apache.org/foundation/sponsorship.html" title="Visit page outside Confluence" rel="nofollow">sponsorship<sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span></li> |
| <li><span class="nobr"><a href="http://www.apache.org/foundation/thanks.html" title="Visit page outside Confluence" rel="nofollow">sponsors<sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span> |
| <!-- ApacheCon Ad --> |
| <iframe src="service-requirement-handler_files/button.html" style="border-width: 0pt; float: left;" scrolling="no" width="135" frameborder="0" height="135"></iframe> |
| <p style="height: 100px;"> |
| <!-- ApacheCon Ad --> |
| </p></li></ul> </div> |
| <div class="main"> |
| <table class="sectionMacro" border="0" cellpadding="5" cellspacing="0" width="100%"><tbody><tr> |
| <td class="confluenceTd" valign="top" width="80%"> |
| <h1><a name="ServiceRequirementHandler-ServiceDependencyManagement"></a>Service Dependency Management</h1> |
| |
| <p>The dependency handler manages <em>OSGi service</em> <em>dependencies/requirements</em>. |
| It allows a component to consume service without managing service |
| discovery, tracking and binding. The handler manages all this |
| interaction and injects required service in the component.</p> |
| |
| <h2><a name="ServiceRequirementHandler-ServiceRequirement"></a>Service Requirement</h2> |
| |
| |
| <h3><a name="ServiceRequirementHandler-What'saservicerequirement?"></a>What's a service requirement?</h3> |
| |
| <p>A requirement represents a required service. Therefore, it manages |
| the service lookup and the service binding. When an instance requires a |
| service, the handler injects directly a service object inside a field, |
| or invokes a method when a consistent service appears (or disappears). |
| Service requirements can be:</p> |
| <ul> |
| <li>Simple / Aggregate : the component can require one or several service providers</li> |
| <li>Mandatory / Optional : a component can declare an optional dependency</li> |
| <li>Filtered : a component can filter available providers</li> |
| <li>Dynamic / Static / Dynamic-Priority : the component can specify the binding policy</li> |
| <li>Specific : the dependency targets a specific service provider</li> |
| </ul> |
| |
| |
| <h3><a name="ServiceRequirementHandler-Dynamism&InstanceLifecycle"></a>Dynamism & Instance Lifecycle</h3> |
| |
| <p>In OSGi™, services can appear and disappear dynamically. This |
| implies dependencies can target a provider which can appear or |
| disappear dynamically. So, dependencies need to manage this |
| dynamism by tracking every time available services. At any moment, a |
| dependency can be unresolved (i.e. no more provider can fulfill the |
| requirement). In the case of a mandatory requirement, the |
| instance becomes invalid (an invalid instance is no more accessible |
| externally, for example provided service are unpublished). If a |
| service, resolving the unfilled dependency appears, the instance |
| becomes valid. In consequence, dependencies affect directly the |
| instance state, and must manage correctly OSGi dynamism to allow a |
| complete unloading when a service goes away. As soon a mandatory |
| dependency cannot be fulfilled, the instance is invalidated.</p> |
| |
| <p>By default, dependencies are managed dynamically (as previously |
| explained). However, iPOJO supports two other types of binding |
| policies: </p> |
| <ul> |
| <li>Static : if a bound service disappears, the instance is invalidated and cannot be revalidated (binding broken)</li> |
| <li>Dynamic-Priority: at each injection, the <em>best</em> provider is injected, or the providers array is sorted according to the OSGi Ranking policy.</li> |
| </ul> |
| |
| |
| <h2><a name="ServiceRequirementHandler-ServiceRequirementInjectionMechanisms"></a>Service Requirement Injection Mechanisms</h2> |
| |
| <p>The handler manages two types of injections:</p> |
| <ul> |
| <li>Field injection: a field contains the service object. As soon |
| as the field is used, a consistent service object is injected. This |
| injection type fully hides the dynamism</li> |
| <li>Method invocation: |
| when a service appears, or disappears a method in the component is |
| invoked. For each dependency, bind and unbind methods are invoke to |
| notify the component of the event.</li> |
| </ul> |
| |
| |
| <p>Moreover, the two injections type can be merged. A component can declare a requirement containing both a field and 'binding'.</p> |
| |
| <h3><a name="ServiceRequirementHandler-Fieldinjection"></a>Field injection</h3> |
| |
| <p>Imagine a Hello service with one method 'getMessage' returning a |
| "Hello Message". The following component implementation can use this |
| service by attaching this service to a field and by using the field:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hello; |
| <span class="code-keyword">public</span> doSomething() { |
| <span class="code-object">System</span>.out.println(m_hello.getMesage()); |
| } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hello"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>The metadata contains a 'requires' element (representing the service |
| dependency). This element has a field attribute. This attribute is the |
| name of the field representing the service dependency in the |
| implementation class. The implementation uses the field as a normal |
| field without managing service interactions.</p> |
| |
| <h3><a name="ServiceRequirementHandler-Methodinvocation"></a>Method invocation</h3> |
| |
| <p>The second injection mechanism uses methods in the implementation |
| class. By this way, the dynamics can be managed directly by the |
| developer. Each dependency can declare two methods:</p> |
| <ul> |
| <li>A bind method called when a service appears</li> |
| <li>An unbind method called when a service disappears</li> |
| </ul> |
| |
| |
| <p>Moreover, callbacks can be in the component super class (in this |
| case methods must be public). These methods can have one of these four |
| signatures:</p> |
| <ul> |
| <li>Without any argument: the method is just a notification (method())</li> |
| <li>With the service object : the object is the implicated service object (method(Service svc))</li> |
| <li>With an OSGi service reference: the service reference appearing or disappearing (method(ServiceReference ref))</li> |
| <li>With the service object and the OSGi service reference (method(Service svc, ServiceReference ref))</li> |
| <li>With the service object and the service properties inside a Map (method(Service svc, Map properties)) <b>[New in the 1.1.0-SNAPSHOT version]</b></li> |
| <li>With the service object and the service properties inside a Dictionary (method(Service svc, Dictionary properties)) <b>[New in the 1.1.0-SNAPSHOT version]</b></li> |
| </ul> |
| |
| |
| <p>The following component implementation shows an example of implementation using this mechanism:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hello; |
| |
| <span class="code-keyword">public</span> void bindHello(Hello h) { m_hello = h; } |
| <span class="code-keyword">public</span> void unbindHello() { m_hello = <span class="code-keyword">null</span>; } |
| <span class="code-keyword">public</span> doSomething() { <span class="code-object">System</span>.out.println(m_hello.getMesage()); } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>Note, that the bind the unbind method can be have different |
| signatures. By using this mechanism, you need to be sure to manage the |
| dynamism correctly.<br> |
| (<a href="#ServiceRequirementHandler-discovery" title="discovery on Service Requirement Handler">See note on type discovery</a>)</p> |
| |
| <h3><a name="ServiceRequirementHandler-FieldinjectionsandMethodinvocations"></a>Field injections and Method invocations</h3> |
| |
| <p>The two mechanisms can be used together. In this case, the field |
| receives the value before the bind method invocation. So, if the field |
| is use in the method, the returned value will be up to date. The |
| following component implementation uses this mechanism:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hello; <span class="code-comment">// Injected Field |
| </span> |
| <span class="code-keyword">public</span> void bindHello() { <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello appears"</span>); } |
| <span class="code-keyword">public</span> void unbindHello() { <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello disapears"</span>); } |
| <span class="code-keyword">public</span> doSomething() { <span class="code-object">System</span>.out.println(m_hello.getMesage()); } |
| }</pre> |
| </div></div> |
| |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| |
| <h3><a name="ServiceRequirementHandler-Injectionmechanisms&lazyobjectcreation"></a>Injection mechanisms & lazy object creation</h3> |
| |
| <p>IPOJO creates objects only when required. When needed, iPOJO invokes |
| the constructor of the implementation class. The implementation class |
| can use field requirement because values are already injected. However, |
| method dependencies are called just after the constructor. If the |
| service already presents, the invocation of the methods are delayed |
| just after the constructor invocation.</p> |
| |
| <h2><a name="ServiceRequirementHandler-SomeExamples"></a>Some Examples</h2> |
| |
| |
| <h3><a name="ServiceRequirementHandler-SimpleRequirement"></a>Simple Requirement</h3> |
| |
| <p>By default, a requirement is mandatory, non-filtered and simple |
| (non-aggregate). The two previous examples illustrate this kind of |
| dependency. When services goes away and appears, the service |
| substitution is hidden. Fields attached to simple requirement point |
| always a consistent service object. For a simple dependency, the bind |
| method is called once time when the service appears or just after the |
| POJO constructor invocation is the service is available. When the |
| service disappears the unbind method is called. The bind method is |
| re-invoked as soon as another service provider is available. This |
| invocation occurs immediately if another service provider if available. |
| In this case, the instance is not invalidated.</p> |
| |
| <h3><a name="ServiceRequirementHandler-AggregateRequirement"></a>Aggregate Requirement</h3> |
| |
| <p>When a component requires several providers of the same service, it declares an aggregate dependency.</p> |
| |
| <h4><a name="ServiceRequirementHandler-AggregateDependencywithfieldinjection"></a>Aggregate Dependency with field injection</h4> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hellos[]; |
| <span class="code-keyword">public</span> doSomething() { |
| <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.length; i++) { |
| <span class="code-object">System</span>.out.println(m_hellos[i].getMessage()); |
| } |
| } |
| }</pre> |
| </div></div> |
| |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| |
| <p>To declare an aggregate field for field requirement, you only need |
| to declare an array (instead of a scalar type). IPOJO will create and |
| inject the service object array. iPOJO discover that the dependency is |
| aggregate during the bytecode introspection.</p> |
| |
| <p><em>Note:</em> The synchronization is managed by iPOJO. As soon as |
| you are 'touching' a dependency in a method, iPOJO ensure that you will |
| keep these objects until the end of the method. Nested methods will |
| share the same service object set.</p> |
| |
| <h4><a name="ServiceRequirementHandler-AggregateDependencywithfieldinjection:list,vector,collectionandset"></a>Aggregate Dependency with field injection: list, vector, collection and set</h4> |
| <p>It is also possible to inject service objects inside fields of the type:</p> |
| <ul> |
| <li>list</li> |
| <li>vector</li> |
| <li>collection</li> |
| <li>set</li> |
| </ul> |
| |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> List m_hellos; |
| <span class="code-keyword">public</span> doSomething() { |
| <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.size(); i++) { |
| <span class="code-object">System</span>.out.println(((Hello) m_hellos.get(i)). |
| getMessage()); |
| } |
| } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> specification=<span class="code-quote">"o.a.f.i.Hello"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>In this case, just use the supported type that you want. iPOJO will |
| automatically understand that it is an aggregate dependency, and will |
| create the collection object containing service objects.<br> |
| <em>Note:</em> The service specification (i.e. interface) cannot be |
| discovered when using these types as the bytecode does not provide |
| enough information. So, you have to indicate the required service |
| interface (with the 'specification' attribute) in the requirement |
| description.<br> |
| <em>Note:</em> As in the previous case, the synchronization is managed |
| by iPOJO. As soon as you are 'touching' a dependency in a method, iPOJO |
| ensure that you will keep these objects until the end of the method. |
| Nested methods will share the same service object set.</p> |
| |
| |
| <h4><a name="ServiceRequirementHandler-AggregateDependencywithmethodinvocation"></a>Aggregate Dependency with method invocation</h4> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> List m_hellos= <span class="code-keyword">new</span> ArrayList(); |
| <span class="code-keyword">private</span> void bindHello(Hello h) { m_hellos.add(h); } |
| <span class="code-keyword">private</span> void unbindHello(Hello h) { m_hellos.remove(h); } |
| <span class="code-keyword">public</span> <span class="code-keyword">synchronized</span> doSomething() { |
| <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.size(); i++) { |
| <span class="code-object">System</span>.out.println(m_hellos.get(i). |
| getMessage()); |
| } |
| } |
| } |
| }</pre> |
| </div></div> |
| <p>This requirement is configured as following:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><requires aggregate=<span class="code-quote">"true"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span></pre> |
| </div></div> |
| <p>In this case, iPOJO cannot detect if the dependency is aggregate or not. So, you need to add the '<em>aggregate</em>' attribute. The bindHello and unbindHello will be called each time a Hello service appears or disappears.<br> |
| <em>Note:</em> To avoid the list modification during the loop, you need |
| synchronized the block. Indeed, as the field is not an iPOJO |
| requirement, iPOJO will not manage the synchronization.</p> |
| |
| <h3><a name="ServiceRequirementHandler-OptionalRequirement(nonaggregate)"></a>Optional Requirement (non-aggregate)</h3> |
| |
| <p>An optional requirement does not invalidate the instance despite no |
| providers are available. Moreover, it is possible to inject a default |
| service implementation when no <em>real</em> providers are available.</p> |
| |
| <h4><a name="ServiceRequirementHandler-OptionalRequirementwithfieldinjection"></a>Optional Requirement with field injection</h4> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hello; |
| <span class="code-keyword">public</span> doSomething() { |
| <span class="code-object">System</span>.out.println(m_hello.getMesage()); |
| } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hello"</span> optional=<span class="code-quote">"true"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>To declare an optional requirement, you need to add the <em>'optional'</em> attribute. To avoid null pointer exception, iPOJO injects a <em>Nullable</em> object in the field when no service provider is available. The <em>nullable</em> |
| object implements the service interface, but does nothing. Moreover, it |
| is possible to set a default-implementation for the service. A |
| default-implementation is a class implementing the service but used |
| only when no others service providers are available. The |
| default-implementation object will be injected instead of the <em>Nullable</em> objet. For further information <a href="#ServiceRequirementHandler-nullable" title="nullable on Service Requirement Handler">refer to the note about nullable object</a>.</p> |
| |
| <h4><a name="ServiceRequirementHandler-OptionalDependencywithmethodinvocation"></a>Optional Dependency with method invocation</h4> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hello; |
| <span class="code-keyword">public</span> void bindHello(Hello h) { m_hello = h; } |
| <span class="code-keyword">public</span> void unbindHello() { m_hello = <span class="code-keyword">null</span>; } |
| <span class="code-keyword">public</span> doSomething() { |
| <span class="code-keyword">if</span>(m_hello != <span class="code-keyword">null</span>) { |
| <span class="code-object">System</span>.out.println(m_hello.getMesage()); |
| } |
| } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata should be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires optional=<span class="code-quote">"true"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>As for field requirement, the dependency metadata needs to contain |
| the optional attribute. IPOJO invokes the method only when a 'real' |
| service is available, so you need to test if m_hello is null before to |
| use it.</p> |
| |
| <h3><a name="ServiceRequirementHandler-Aggregate&OptionalRequirement"></a>Aggregate & Optional Requirement</h3> |
| |
| <p>A dependency can be both aggregate and optional.</p> |
| |
| <h4><a name="ServiceRequirementHandler-Aggregate&OptionalDependencywithfieldinjection"></a>Aggregate & Optional Dependency with field injection</h4> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> Hello m_hellos[]; |
| <span class="code-keyword">public</span> doSomething() { |
| <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.length; i++) { |
| <span class="code-object">System</span>.out.println(m_hellos[i].getMessage()); |
| } |
| } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> optional=<span class="code-quote">"true"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>To declare an optional & aggregate field requirement you need to |
| write the optional attribute in the dependency metadata and to point on |
| a field array. If no service available, iPOJO injects an empty array.</p> |
| |
| <h4><a name="ServiceRequirementHandler-Aggregate&OptionalRequirementwithmethodinvocation"></a>Aggregate & Optional Requirement with method invocation</h4> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| <span class="code-keyword">private</span> List m_hellos<Hello> = <span class="code-keyword">new</span> ArrayList<Hello>(); |
| <span class="code-keyword">private</span> void bindHello(Hello h) { m_hellos.add(h); } |
| <span class="code-keyword">private</span> void unbindHello(Hello h) { m_hellos.remove(h); } |
| <span class="code-keyword">public</span> <span class="code-keyword">synchronized</span> doSomething() { |
| <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.size(); i++) { |
| <span class="code-object">System</span>.out.println(m_hellos.get(i).getMessage()); |
| } |
| } |
| }</pre> |
| </div></div> |
| <p>For this component, metadata could be:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><requires aggregate=<span class="code-quote">"true"</span> optional=<span class="code-quote">"true"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span></pre> |
| </div></div> |
| <p>In this case, you need to add the _'aggregate'_attribute and the |
| _'optional'_attribute. The bindHello and unbindHello will be called |
| each time a Hello service appears or disappears. These bind / unbind |
| methods are not called when binding / unbinding a Nullable object (when |
| both field and method are used).</p> |
| |
| <h3><a name="ServiceRequirementHandler-FilteredRequirement"></a>Filtered Requirement</h3> |
| |
| <p>A filtered dependency applies an LDAP filter on service provider. |
| IPOJO reuses OSGi LDAP filter ability. The following metadata |
| illustrates how to use filters:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires filter=<span class="code-quote">"(language=fr)"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>To add a filter, just add a 'filter' attribute in your dependency |
| containing the LDAP filter. iPOJO will select only provider matching |
| with this filter.</p> |
| |
| <p>Moreover, filters can be customized instance by instance. It is |
| possible to specialize / change / add the filter of a component in the |
| instance description. It is useful when you want to create different |
| instances of the same component, with different filter. To do it, you |
| have to identify your dependency with an 'id' attribute. Then, you can |
| adapt the filter of the dependency in the instance description by using |
| the property "requires.filters". In this property you can specify each |
| dependency identified by its id and the new value of the filter.</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><component |
| className=<span class="code-quote">"org.apache.felix.ipojo.example.FilteredDependency"</span> |
| name=<span class="code-quote">"FOO"</span>> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_foo"</span> fiter=<span class="code-quote">"(foo.property=FOO)"</span> id=<span class="code-quote">"id1"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bind"</span>/></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbind"</span>/></span> |
| <span class="code-tag"></requires></span> |
| <span class="code-tag"></component></span> |
| |
| <span class="code-tag"><instance name=<span class="code-quote">"FOO1"</span> component=<span class="code-quote">"FOO"</span>/></span> |
| |
| <span class="code-tag"><instance name=<span class="code-quote">"FOO2"</span> component=<span class="code-quote">"FOO"</span>></span> |
| |
| <span class="code-tag"><property name=<span class="code-quote">"requires.filters"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"(foo.property=BAR)"</span>/></span> |
| <span class="code-tag"></property></span> |
| <span class="code-tag"></instance></span> |
| |
| <span class="code-tag"><instance name=<span class="code-quote">"FOO3"</span> component=<span class="code-quote">"FOO"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"requires.filters"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"(foo.property=BAZ)"</span>/></span> |
| <span class="code-tag"></property></span> |
| <span class="code-tag"></instance></span></pre> |
| </div></div> |
| <p>The FOO component type declares a service dependency with the 'id1' |
| id. This dependency has no filter by default. The first instance is |
| just an instance of the FOO component type and does not modify the |
| dependency. The second one adds a filter to the declared dependency to |
| target providers with foo.property = BAR. The last one adds another |
| filter to the declared dependency. By using instance filter |
| customization, it is possible to create complex applications where you |
| avoid binding problems by filtering dependencies instance by instance.</p> |
| |
| <h3><a name="ServiceRequirementHandler-Targetingaspecificprovider"></a>Targeting a specific provider</h3> |
| <p>A service dependency can choose a specific provider. To achieve |
| this, add a 'from' attribute in your requirement description such as in:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires from=<span class="code-quote">"MyHelloProvider"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| <span class="code-tag"></requires></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>iPOJO maps the from attribute to a specific filter : |
| '|(instance.name=MyHelloProvider)(service.pid=MyHelloProvider)'. Then |
| the dependency can only be fulfilled by a service matching this filter.</p> |
| |
| <p>Moreover, from attributes can be customized instance by instance. It |
| is possible to specialize / change / add a 'from' attribute of a |
| component in the instance configuration. It is useful when you want to |
| create different instances of the same component, with different 'from' |
| clauses. To do it, you have to identify your dependency with an 'id' |
| attribute. Then, you can adapt the 'from' of the dependency in the |
| instance configuration by using the property "requires.from". In this |
| property you can specify each dependency identified by its id and the |
| 'from' value.</p> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><component |
| className=<span class="code-quote">"org.apache.felix.ipojo.example.FilteredDependency"</span> |
| name=<span class="code-quote">"FOO"</span>> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_foo"</span> id=<span class="code-quote">"id1"</span>></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bind"</span>/></span> |
| <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbind"</span>/></span> |
| <span class="code-tag"></requires></span> |
| <span class="code-tag"></component></span> |
| |
| <span class="code-tag"><instance name=<span class="code-quote">"FOO1"</span> component=<span class="code-quote">"FOO"</span>/></span> |
| |
| <span class="code-tag"><instance name=<span class="code-quote">"FOO2"</span> component=<span class="code-quote">"FOO"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"requires.from"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"myprovider"</span>/></span> |
| <span class="code-tag"></property></span> |
| <span class="code-tag"></instance></span> |
| |
| <span class="code-tag"><instance name=<span class="code-quote">"FOO3"</span> component=<span class="code-quote">"FOO"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"requires.from"</span>></span> |
| <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"myotherprovider"</span>/></span> |
| <span class="code-tag"></property></span> |
| <span class="code-tag"></instance></span></pre> |
| </div></div> |
| |
| <p>The FOO component type declares a service dependency with the 'id1' |
| id. This dependency has no 'from' attribute by default. The first |
| instance is just an instance of the FOO component type and does not |
| modify the dependency. The second one adds a 'from' attribute to the |
| declared dependency to target the 'myprovider' provider. The last one |
| adds another 'from' clause to the declared dependency.</p> |
| |
| |
| <h2><a name="ServiceRequirementHandler-BindingPolicies"></a>Binding Policies</h2> |
| |
| <p>Three binding policies are supported inside iPOJO.</p> |
| <ul> |
| <li>Dynamic policy (default): the binding are managed |
| dynamically. At each injection, the same provider is injected if the |
| provider is always available. Else a new one is chosen. For aggregate |
| dependency, the array order does not change; new providers are placed |
| at the end of the array.</li> |
| <li>Static policy: the binding is |
| static. So, once bound a provider cannot disappear. If it disappears, |
| the instance is invalidated and cannot be revalidated without stopping |
| and restarting the instance.</li> |
| <li>Dynamic-priority policy: the |
| binding is managed dynamically but the injected provider is selected by |
| using a ranking policy. Two injections can return two different |
| providers, is a new provider is 'better' than the previous one, despite |
| the first one is always available. For aggregate dependency, the array |
| is sorted.</li> |
| </ul> |
| |
| |
| |
| <p>A static binding is declared as following:</p> |
| |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> policy=<span class="code-quote">"static"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| |
| <p>A dynamic-priority binding is declared as following:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> policy=<span class="code-quote">"dynamic-priority"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>By default, the dynamic-priority policy uses the OSGi service |
| ranking policy. However, it is possible to customize the policy by |
| adding the '<em>comparator</em>' attribute. This attribute indicates |
| the class name of a class implementing the java.util.Comparator |
| interface. IPOJO will create an instance of your comparator and use it |
| to sort service references (so your customized comparator needs to be |
| able to sort OSGi Service Reference).</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> policy=<span class="code-quote">"dynamic-priority"</span> comparator=<span class="code-quote">"my.great.Comparator"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| |
| <p><a name="ServiceRequirementHandler-nullable"></a></p> |
| <h2><a name="ServiceRequirementHandler-Noteaboutnullableobject&defaultimplementation"></a>Note about nullable object & default-implementation</h2> |
| |
| <p>The instance implementation can use an optional dependency without |
| any checking. Indeed, when an instance declares an optional dependency |
| using field injection, iPOJO create on the fly a Nullable class |
| implementing the service specification but doing nothing (mock object). |
| Therefore, iPOJO cannot return a service to the instance, for an |
| optional dependency, it returns a nullable object.</p> |
| |
| <p>A nullable object returns:</p> |
| <ul> |
| <li>Null when the method returns an object</li> |
| <li>0 when the method returns an int, log, byte, short, char, float or a double</li> |
| <li>False when the method return a boolean</li> |
| </ul> |
| |
| |
| <p>You can check if the returned object is a nullable object with the test: <em>"myservice instanceof Nullable"</em>.</p> |
| |
| <p>You can disable the Nullable pattern too (activated by default). In this case, iPOJO will inject <em>null</em> instead of a <em>Nullable</em> object. So, you can just test if your field is equals to <em>null</em> |
| to check if the service is available. To disable the Nullable pattern, |
| you need to add the 'nullable="false"' attribute in your service |
| dependency description as follows:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...LogExample"</span>></span> |
| <span class="code-tag"><requires field=<span class="code-quote">"m_log"</span> optional=<span class="code-quote">"true"</span> nullable=<span class="code-quote">"false"</span>/></span> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| |
| <p>However, you can also indicate a <em>default-implementation</em> for |
| your optional service. In this case, if no providers are found, iPOJO |
| creates an instance of the default-implementation and injects it. The |
| default-implementation attribute describes the class name of your |
| implementation. The given class <b>MUST</b> implement the required service interface.</p> |
| |
| <p>For example, the following component uses a default implementation for a Log Service dependency:</p> |
| <div class="code"><div class="codeContent"> |
| <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...LogExample"</span>></span> |
| <requires field=<span class="code-quote">"m_log"</span> optional=<span class="code-quote">"true"</span> |
| default-implementation= |
| <span class="code-quote">"org.apache.felix.ipojo.example.default.MyLogService"</span>/> |
| ... |
| <span class="code-tag"></component></span></pre> |
| </div></div> |
| <p>If the log service is not available, iPOJO creates an object of the |
| 'org.apache.felix.ipojo.example.default.MyLogService' class. This |
| object is injected instead of a Nullable object. For instance, the |
| default implementation can print messages on the System.err stream. The |
| nullable object does no display anything.</p> |
| |
| |
| <p><a name="ServiceRequirementHandler-callbacks"></a></p> |
| <h2><a name="ServiceRequirementHandler-NoteaboutCallbacks"></a>Note about Callbacks</h2> |
| <p>Dependency manages two type of callback: bind and unbind. A callback |
| with a type "bind" is called each type that a service provider arrives |
| and the binding is necessary. According to the cardinality of the |
| dependency it means:</p> |
| <ul> |
| <li>Simple dependency : at the firs binding and at each rebinding to another service provider</li> |
| <li>Aggregate dependencies: each time that a service provider arrives</li> |
| </ul> |
| |
| |
| <p>An unbind callback is called each time that a <b>used</b> service |
| provider goes away. For a simple dependency this method is called each |
| time that the used service provider goes away. For a multiple |
| dependency this method is called each time that a service provider goes |
| away.</p> |
| |
| <p>The method can receive in argument the service object or the service |
| reference (in order to obtain service properties). The bind methods are |
| delayed since a POJO object is created.</p> |
| |
| <p><a name="ServiceRequirementHandler-discovery"></a></p> |
| <h2><a name="ServiceRequirementHandler-Noteonserviceinterfacediscovery"></a>Note on service interface discovery</h2> |
| |
| <p>The <tt>specification</tt> attribute is generally optional except |
| when iPOJO cannot discover the type of the service. iPOJO cannot infer |
| the type when the dependency has no field and callbacks do not receive |
| the service object in parameter. In this case, you need to declare the |
| service interface.</p> |
| </td> |
| <td class="confluenceTd" valign="top" width="20%"> |
| <h6><a name="ServiceRequirementHandler-Overview"></a><b>Overview</b></h6> |
| <ul> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo.html" title="Apache Felix iPOJO">Home Page</a></li> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo-feature-overview.html" title="Apache Felix iPOJO Feature Overview">iPOJO Feature Overview</a></li> |
| <li><a href="http://felix.apache.org/site/download.html" title="Download">Download & Install </a></li> |
| </ul> |
| |
| |
| <h6><a name="ServiceRequirementHandler-GettingStarted"></a><b>Getting Started</b></h6> |
| <ul> |
| <li><a href="http://felix.apache.org/site/ipojo-in-10-minutes.html" title="iPOJO in 10 minutes">iPOJO in 10 minutes</a></li> |
| <li><a href="http://felix.apache.org/site/how-to-use-ipojo-annotations.html" title="How to use iPOJO Annotations">How to use iPOJO Annotations</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-hello-word-maven-based-tutorial.html" title="iPOJO Hello Word (Maven-Based) tutorial">iPOJO Hello Word (Maven-Based) tutorial</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-advanced-tutorial.html" title="iPOJO Advanced Tutorial">iPOJO Advanced Tutorial</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-composition-tutorial.html" title="iPOJO Composition Tutorial">iPOJO Composition Tutorial</a></li> |
| </ul> |
| |
| |
| <h6><a name="ServiceRequirementHandler-UserGuide"></a><b>User Guide</b></h6> |
| <ul> |
| <li><a href="http://felix.apache.org/site/describing-components.html" title="Describing components">Describing components (handler list) </a></li> |
| <li><a href="http://felix.apache.org/site/using-xml-schemas.html" title="Using XML Schemas">Using XML Schemas</a></li> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo-testing-components.html" title="apache-felix-ipojo-testing-components">Testing components</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-advanced-topics.html" title="iPOJO Advanced Topics">Advanced Topics</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-faq.html" title="iPOJO FAQ">FAQ</a></li> |
| </ul> |
| |
| |
| <h6><a name="ServiceRequirementHandler-Tools"></a><b>Tools</b></h6> |
| <ul> |
| <li><a href="http://felix.apache.org/site/ipojo-eclipse-plug-in.html" title="iPOJO Eclipse Plug-in">iPOJO Eclipse Plug-in</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-ant-task.html" title="iPOJO Ant Task">iPOJO Ant Task</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-maven-plug-in.html" title="iPOJO Maven Plug-in">iPOJO Maven Plug-in</a></li> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo-junit4osgi.html" title="apache-felix-ipojo-junit4osgi">Junit4OSGi</a></li> |
| <li><a href="http://felix.apache.org/site/ipojo-concepts-overview.html" title="iPOJO Concepts Overview">iPOJO concepts overview</a></li> |
| </ul> |
| |
| |
| <h6><a name="ServiceRequirementHandler-DeveloperGuide"></a><b>Developer Guide</b></h6> |
| <ul> |
| <li>API: <span class="nobr"><a href="http://people.apache.org/%7Eclement/ipojo/api/1.0/" title="Visit page outside Confluence" rel="nofollow">1.0<sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span></li> |
| <li><a href="http://felix.apache.org/site/how-to-write-your-own-handler.html" title="How to write your own handler">How to write your own handler</a></li> |
| <li><a href="http://felix.apache.org/site/how-to-use-ipojo-manipulation-metadata.html" title="How to use iPOJO Manipulation Metadata">How to use iPOJO Manipulation Metadata</a></li> |
| <li><a href="http://felix.apache.org/site/dive-into-the-ipojo-manipulation-depths.html" title="Dive into the iPOJO Manipulation depths">Dive into the iPOJO Manipulation depths</a></li> |
| </ul> |
| |
| |
| <h6><a name="ServiceRequirementHandler-Misc&Contact"></a><b>Misc & Contact</b></h6> |
| <ul> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo-issuestracker.html" title="apache-felix-ipojo-issuestracker">Issues Tracker</a></li> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo-supportedvms.html" title="apache-felix-ipojo-supportedVMs">Supported JVMs</a></li> |
| <li><a href="http://felix.apache.org/site/apache-felix-ipojo-supportedosgi.html" title="apache-felix-ipojo-supportedOSGi">Supported OSGi Implementations</a></li> |
| <li><span class="nobr"><a href="http://ipojo-dark-side.blogspot.com/" title="Visit page outside Confluence" rel="nofollow">iPOJO's Dark Side Blog<sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span></li> |
| <li><a href="http://felix.apache.org/site/future-ideas.html" title="Future Ideas">Future Ideas</a></li> |
| <li><a href="http://felix.apache.org/site/contact.html" title="Contact">Contact</a></li> |
| <li><a href="http://felix.apache.org/site/related-works.html" title="Related Works">Related Works</a></li> |
| <li><a href="http://felix.apache.org/site/article-presentations.html" title="Article & Presentations">Article & Presentations</a></li> |
| </ul> |
| |
| |
| <hr> |
| <div class="" align="center"> |
| <p><span class="nobr"><a href="http://cwiki.apache.org/confluence/createrssfeed.action?types=blogpost&statuses=created&statuses=modified&spaces=FELIX&labelString=iPOJO&rssType=atom&maxResults=10&timeSpan=5&publicFeed=true&title=iPOJO%20Atom%20Feed" title="Stay tuned!" rel="nofollow"><img src="service-requirement-handler_files/feed-icon-32x32.png" align="absmiddle" border="0"><sup><img class="rendericon" src="service-requirement-handler_files/linkext7.gif" alt="" align="absmiddle" border="0" width="7" height="7"></sup></a></span></p></div> |
| |
| <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 src="service-requirement-handler_files/ga.js" type="text/javascript"></script> |
| <script type="text/javascript"> |
| var pageTracker = _gat._getTracker("UA-1518442-4"); |
| pageTracker._trackPageview(); |
| </script> |
| </td></tr></tbody></table> |
| </div> |
| </body></html> |