Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 2 | <html><head> |
| 3 | |
| 4 | |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 5 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 6 | <title>Apache Felix - Service Requirement Handler</title> |
| 7 | <link rel="stylesheet" href="service-requirement-handler_files/site.css" type="text/css" media="all"> |
| 8 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| 9 | </head><body> |
| 10 | <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> |
| 11 | <div class="menu"> |
| 12 | <ul> |
| 13 | <li><a href="http://felix.apache.org/site/news.html" title="news">news</a></li> |
| 14 | <li><a href="http://felix.apache.org/site/license.html" title="license">license</a></li> |
| 15 | <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> |
| 16 | <li><a href="http://felix.apache.org/site/documentation.html" title="documentation">documentation</a></li> |
| 17 | <li><a href="http://felix.apache.org/site/mailinglists.html" title="mailinglists">mailing lists</a></li> |
| 18 | <li><a href="http://felix.apache.org/site/contributing.html" title="Contributing">contributing</a></li> |
| 19 | <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> |
| 20 | <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> |
| 21 | <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> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 22 | <!-- ApacheCon Ad --> |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 23 | <iframe src="service-requirement-handler_files/button.html" style="border-width: 0pt; float: left;" scrolling="no" width="135" frameborder="0" height="135"></iframe> |
| 24 | <p style="height: 100px;"> |
| 25 | <!-- ApacheCon Ad --> |
| 26 | </p></li></ul> </div> |
| 27 | <div class="main"> |
| 28 | <table class="sectionMacro" border="0" cellpadding="5" cellspacing="0" width="100%"><tbody><tr> |
| 29 | <td class="confluenceTd" valign="top" width="80%"> |
| 30 | <h1><a name="ServiceRequirementHandler-ServiceDependencyManagement"></a>Service Dependency Management</h1> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 31 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 32 | <p>The dependency handler manages <em>OSGi service</em> <em>dependencies/requirements</em>. |
| 33 | It allows a component to consume service without managing service |
| 34 | discovery, tracking and binding. The handler manages all this |
| 35 | interaction and injects required service in the component.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 36 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 37 | <h2><a name="ServiceRequirementHandler-ServiceRequirement"></a>Service Requirement</h2> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 38 | |
| 39 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 40 | <h3><a name="ServiceRequirementHandler-What'saservicerequirement?"></a>What's a service requirement?</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 41 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 42 | <p>A requirement represents a required service. Therefore, it manages |
| 43 | the service lookup and the service binding. When an instance requires a |
| 44 | service, the handler injects directly a service object inside a field, |
| 45 | or invokes a method when a consistent service appears (or disappears). |
| 46 | Service requirements can be:</p> |
| 47 | <ul> |
| 48 | <li>Simple / Aggregate : the component can require one or several service providers</li> |
| 49 | <li>Mandatory / Optional : a component can declare an optional dependency</li> |
| 50 | <li>Filtered : a component can filter available providers</li> |
| 51 | <li>Dynamic / Static / Dynamic-Priority : the component can specify the binding policy</li> |
| 52 | <li>Specific : the dependency targets a specific service provider</li> |
| 53 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 54 | |
| 55 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 56 | <h3><a name="ServiceRequirementHandler-Dynamism&InstanceLifecycle"></a>Dynamism & Instance Lifecycle</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 57 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 58 | <p>In OSGi™, services can appear and disappear dynamically. This |
| 59 | implies dependencies can target a provider which can appear or |
| 60 | disappear dynamically. So, dependencies need to manage this |
| 61 | dynamism by tracking every time available services. At any moment, a |
| 62 | dependency can be unresolved (i.e. no more provider can fulfill the |
| 63 | requirement). In the case of a mandatory requirement, the |
| 64 | instance becomes invalid (an invalid instance is no more accessible |
| 65 | externally, for example provided service are unpublished). If a |
| 66 | service, resolving the unfilled dependency appears, the instance |
| 67 | becomes valid. In consequence, dependencies affect directly the |
| 68 | instance state, and must manage correctly OSGi dynamism to allow a |
| 69 | complete unloading when a service goes away. As soon a mandatory |
| 70 | dependency cannot be fulfilled, the instance is invalidated.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 71 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 72 | <p>By default, dependencies are managed dynamically (as previously |
| 73 | explained). However, iPOJO supports two other types of binding |
| 74 | policies: </p> |
| 75 | <ul> |
| 76 | <li>Static : if a bound service disappears, the instance is invalidated and cannot be revalidated (binding broken)</li> |
| 77 | <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> |
| 78 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 79 | |
| 80 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 81 | <h2><a name="ServiceRequirementHandler-ServiceRequirementInjectionMechanisms"></a>Service Requirement Injection Mechanisms</h2> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 82 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 83 | <p>The handler manages two types of injections:</p> |
| 84 | <ul> |
| 85 | <li>Field injection: a field contains the service object. As soon |
| 86 | as the field is used, a consistent service object is injected. This |
| 87 | injection type fully hides the dynamism</li> |
| 88 | <li>Method invocation: |
| 89 | when a service appears, or disappears a method in the component is |
| 90 | invoked. For each dependency, bind and unbind methods are invoke to |
| 91 | notify the component of the event.</li> |
| 92 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 93 | |
| 94 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 95 | <p>Moreover, the two injections type can be merged. A component can declare a requirement containing both a field and 'binding'.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 96 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 97 | <h3><a name="ServiceRequirementHandler-Fieldinjection"></a>Field injection</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 98 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 99 | <p>Imagine a Hello service with one method 'getMessage' returning a |
| 100 | "Hello Message". The following component implementation can use this |
| 101 | service by attaching this service to a field and by using the field:</p> |
| 102 | <div class="code"><div class="codeContent"> |
| 103 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 104 | <span class="code-keyword">private</span> Hello m_hello; |
| 105 | <span class="code-keyword">public</span> doSomething() { |
| 106 | <span class="code-object">System</span>.out.println(m_hello.getMesage()); |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 107 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 108 | }</pre> |
| 109 | </div></div> |
| 110 | <p>For this component, metadata could be:</p> |
| 111 | <div class="code"><div class="codeContent"> |
| 112 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 113 | <span class="code-tag"><requires field=<span class="code-quote">"m_hello"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 114 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 115 | <span class="code-tag"></component></span></pre> |
| 116 | </div></div> |
| 117 | <p>The metadata contains a 'requires' element (representing the service |
| 118 | dependency). This element has a field attribute. This attribute is the |
| 119 | name of the field representing the service dependency in the |
| 120 | implementation class. The implementation uses the field as a normal |
| 121 | field without managing service interactions.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 122 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 123 | <h3><a name="ServiceRequirementHandler-Methodinvocation"></a>Method invocation</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 124 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 125 | <p>The second injection mechanism uses methods in the implementation |
| 126 | class. By this way, the dynamics can be managed directly by the |
| 127 | developer. Each dependency can declare two methods:</p> |
| 128 | <ul> |
| 129 | <li>A bind method called when a service appears</li> |
| 130 | <li>An unbind method called when a service disappears</li> |
| 131 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 132 | |
| 133 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 134 | <p>Moreover, callbacks can be in the component super class (in this |
| 135 | case methods must be public). These methods can have one of these four |
| 136 | signatures:</p> |
| 137 | <ul> |
| 138 | <li>Without any argument: the method is just a notification (method())</li> |
| 139 | <li>With the service object : the object is the implicated service object (method(Service svc))</li> |
| 140 | <li>With an OSGi service reference: the service reference appearing or disappearing (method(ServiceReference ref))</li> |
| 141 | <li>With the service object and the OSGi service reference (method(Service svc, ServiceReference ref))</li> |
| 142 | <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> |
| 143 | <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> |
| 144 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 145 | |
| 146 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 147 | <p>The following component implementation shows an example of implementation using this mechanism:</p> |
| 148 | <div class="code"><div class="codeContent"> |
| 149 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 150 | <span class="code-keyword">private</span> Hello m_hello; |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 151 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 152 | <span class="code-keyword">public</span> void bindHello(Hello h) { m_hello = h; } |
| 153 | <span class="code-keyword">public</span> void unbindHello() { m_hello = <span class="code-keyword">null</span>; } |
| 154 | <span class="code-keyword">public</span> doSomething() { <span class="code-object">System</span>.out.println(m_hello.getMesage()); } |
| 155 | }</pre> |
| 156 | </div></div> |
| 157 | <p>For this component, metadata could be:</p> |
| 158 | <div class="code"><div class="codeContent"> |
| 159 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 160 | <span class="code-tag"><requires></span> |
| 161 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 162 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 163 | <span class="code-tag"></requires></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 164 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 165 | <span class="code-tag"></component></span></pre> |
| 166 | </div></div> |
| 167 | <p>Note, that the bind the unbind method can be have different |
| 168 | signatures. By using this mechanism, you need to be sure to manage the |
| 169 | dynamism correctly.<br> |
| 170 | (<a href="#ServiceRequirementHandler-discovery" title="discovery on Service Requirement Handler">See note on type discovery</a>)</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 171 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 172 | <h3><a name="ServiceRequirementHandler-FieldinjectionsandMethodinvocations"></a>Field injections and Method invocations</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 173 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 174 | <p>The two mechanisms can be used together. In this case, the field |
| 175 | receives the value before the bind method invocation. So, if the field |
| 176 | is use in the method, the returned value will be up to date. The |
| 177 | following component implementation uses this mechanism:</p> |
| 178 | <div class="code"><div class="codeContent"> |
| 179 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 180 | <span class="code-keyword">private</span> Hello m_hello; <span class="code-comment">// Injected Field |
| 181 | </span> |
| 182 | <span class="code-keyword">public</span> void bindHello() { <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello appears"</span>); } |
| 183 | <span class="code-keyword">public</span> void unbindHello() { <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello disapears"</span>); } |
| 184 | <span class="code-keyword">public</span> doSomething() { <span class="code-object">System</span>.out.println(m_hello.getMesage()); } |
| 185 | }</pre> |
| 186 | </div></div> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 187 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 188 | <p>For this component, metadata could be:</p> |
| 189 | <div class="code"><div class="codeContent"> |
| 190 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 191 | <span class="code-tag"><requires field=<span class="code-quote">"m_hello"</span>></span> |
| 192 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 193 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 194 | <span class="code-tag"></requires></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 195 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 196 | <span class="code-tag"></component></span></pre> |
| 197 | </div></div> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 198 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 199 | <h3><a name="ServiceRequirementHandler-Injectionmechanisms&lazyobjectcreation"></a>Injection mechanisms & lazy object creation</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 200 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 201 | <p>IPOJO creates objects only when required. When needed, iPOJO invokes |
| 202 | the constructor of the implementation class. The implementation class |
| 203 | can use field requirement because values are already injected. However, |
| 204 | method dependencies are called just after the constructor. If the |
| 205 | service already presents, the invocation of the methods are delayed |
| 206 | just after the constructor invocation.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 207 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 208 | <h2><a name="ServiceRequirementHandler-SomeExamples"></a>Some Examples</h2> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 209 | |
| 210 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 211 | <h3><a name="ServiceRequirementHandler-SimpleRequirement"></a>Simple Requirement</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 212 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 213 | <p>By default, a requirement is mandatory, non-filtered and simple |
| 214 | (non-aggregate). The two previous examples illustrate this kind of |
| 215 | dependency. When services goes away and appears, the service |
| 216 | substitution is hidden. Fields attached to simple requirement point |
| 217 | always a consistent service object. For a simple dependency, the bind |
| 218 | method is called once time when the service appears or just after the |
| 219 | POJO constructor invocation is the service is available. When the |
| 220 | service disappears the unbind method is called. The bind method is |
| 221 | re-invoked as soon as another service provider is available. This |
| 222 | invocation occurs immediately if another service provider if available. |
| 223 | In this case, the instance is not invalidated.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 224 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 225 | <h3><a name="ServiceRequirementHandler-AggregateRequirement"></a>Aggregate Requirement</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 226 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 227 | <p>When a component requires several providers of the same service, it declares an aggregate dependency.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 228 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 229 | <h4><a name="ServiceRequirementHandler-AggregateDependencywithfieldinjection"></a>Aggregate Dependency with field injection</h4> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 230 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 231 | <div class="code"><div class="codeContent"> |
| 232 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 233 | <span class="code-keyword">private</span> Hello m_hellos[]; |
| 234 | <span class="code-keyword">public</span> doSomething() { |
| 235 | <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.length; i++) { |
| 236 | <span class="code-object">System</span>.out.println(m_hellos[i].getMessage()); |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 237 | } |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 238 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 239 | }</pre> |
| 240 | </div></div> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 241 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 242 | <p>For this component, metadata could be:</p> |
| 243 | <div class="code"><div class="codeContent"> |
| 244 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 245 | <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 246 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 247 | <span class="code-tag"></component></span></pre> |
| 248 | </div></div> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 249 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 250 | <p>To declare an aggregate field for field requirement, you only need |
| 251 | to declare an array (instead of a scalar type). IPOJO will create and |
| 252 | inject the service object array. iPOJO discover that the dependency is |
| 253 | aggregate during the bytecode introspection.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 254 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 255 | <p><em>Note:</em> The synchronization is managed by iPOJO. As soon as |
| 256 | you are 'touching' a dependency in a method, iPOJO ensure that you will |
| 257 | keep these objects until the end of the method. Nested methods will |
| 258 | share the same service object set.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 259 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 260 | <h4><a name="ServiceRequirementHandler-AggregateDependencywithfieldinjection:list,vector,collectionandset"></a>Aggregate Dependency with field injection: list, vector, collection and set</h4> |
| 261 | <p>It is also possible to inject service objects inside fields of the type:</p> |
| 262 | <ul> |
| 263 | <li>list</li> |
| 264 | <li>vector</li> |
| 265 | <li>collection</li> |
| 266 | <li>set</li> |
| 267 | </ul> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 268 | |
| 269 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 270 | <div class="code"><div class="codeContent"> |
| 271 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 272 | <span class="code-keyword">private</span> List m_hellos; |
| 273 | <span class="code-keyword">public</span> doSomething() { |
| 274 | <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.size(); i++) { |
| 275 | <span class="code-object">System</span>.out.println(((Hello) m_hellos.get(i)). |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 276 | getMessage()); |
| 277 | } |
| 278 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 279 | }</pre> |
| 280 | </div></div> |
| 281 | <p>For this component, metadata could be:</p> |
| 282 | <div class="code"><div class="codeContent"> |
| 283 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 284 | <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> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 285 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 286 | <span class="code-tag"></component></span></pre> |
| 287 | </div></div> |
| 288 | <p>In this case, just use the supported type that you want. iPOJO will |
| 289 | automatically understand that it is an aggregate dependency, and will |
| 290 | create the collection object containing service objects.<br> |
| 291 | <em>Note:</em> The service specification (i.e. interface) cannot be |
| 292 | discovered when using these types as the bytecode does not provide |
| 293 | enough information. So, you have to indicate the required service |
| 294 | interface (with the 'specification' attribute) in the requirement |
| 295 | description.<br> |
| 296 | <em>Note:</em> As in the previous case, the synchronization is managed |
| 297 | by iPOJO. As soon as you are 'touching' a dependency in a method, iPOJO |
| 298 | ensure that you will keep these objects until the end of the method. |
| 299 | Nested methods will share the same service object set.</p> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 300 | |
| 301 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 302 | <h4><a name="ServiceRequirementHandler-AggregateDependencywithmethodinvocation"></a>Aggregate Dependency with method invocation</h4> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 303 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 304 | <div class="code"><div class="codeContent"> |
| 305 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 306 | <span class="code-keyword">private</span> List m_hellos= <span class="code-keyword">new</span> ArrayList(); |
| 307 | <span class="code-keyword">private</span> void bindHello(Hello h) { m_hellos.add(h); } |
| 308 | <span class="code-keyword">private</span> void unbindHello(Hello h) { m_hellos.remove(h); } |
| 309 | <span class="code-keyword">public</span> <span class="code-keyword">synchronized</span> doSomething() { |
| 310 | <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.size(); i++) { |
| 311 | <span class="code-object">System</span>.out.println(m_hellos.get(i). |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 312 | getMessage()); |
| 313 | } |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 314 | } |
| 315 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 316 | }</pre> |
| 317 | </div></div> |
| 318 | <p>This requirement is configured as following:</p> |
| 319 | <div class="code"><div class="codeContent"> |
| 320 | <pre class="code-xml"><span class="code-tag"><requires aggregate=<span class="code-quote">"true"</span>></span> |
| 321 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 322 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 323 | <span class="code-tag"></requires></span></pre> |
| 324 | </div></div> |
| 325 | <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> |
| 326 | <em>Note:</em> To avoid the list modification during the loop, you need |
| 327 | synchronized the block. Indeed, as the field is not an iPOJO |
| 328 | requirement, iPOJO will not manage the synchronization.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 329 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 330 | <h3><a name="ServiceRequirementHandler-OptionalRequirement(nonaggregate)"></a>Optional Requirement (non-aggregate)</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 331 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 332 | <p>An optional requirement does not invalidate the instance despite no |
| 333 | providers are available. Moreover, it is possible to inject a default |
| 334 | service implementation when no <em>real</em> providers are available.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 335 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 336 | <h4><a name="ServiceRequirementHandler-OptionalRequirementwithfieldinjection"></a>Optional Requirement with field injection</h4> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 337 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 338 | <div class="code"><div class="codeContent"> |
| 339 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 340 | <span class="code-keyword">private</span> Hello m_hello; |
| 341 | <span class="code-keyword">public</span> doSomething() { |
| 342 | <span class="code-object">System</span>.out.println(m_hello.getMesage()); |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 343 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 344 | }</pre> |
| 345 | </div></div> |
| 346 | <p>For this component, metadata could be:</p> |
| 347 | <div class="code"><div class="codeContent"> |
| 348 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 349 | <span class="code-tag"><requires field=<span class="code-quote">"m_hello"</span> optional=<span class="code-quote">"true"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 350 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 351 | <span class="code-tag"></component></span></pre> |
| 352 | </div></div> |
| 353 | <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> |
| 354 | object implements the service interface, but does nothing. Moreover, it |
| 355 | is possible to set a default-implementation for the service. A |
| 356 | default-implementation is a class implementing the service but used |
| 357 | only when no others service providers are available. The |
| 358 | 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> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 359 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 360 | <h4><a name="ServiceRequirementHandler-OptionalDependencywithmethodinvocation"></a>Optional Dependency with method invocation</h4> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 361 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 362 | <div class="code"><div class="codeContent"> |
| 363 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 364 | <span class="code-keyword">private</span> Hello m_hello; |
| 365 | <span class="code-keyword">public</span> void bindHello(Hello h) { m_hello = h; } |
| 366 | <span class="code-keyword">public</span> void unbindHello() { m_hello = <span class="code-keyword">null</span>; } |
| 367 | <span class="code-keyword">public</span> doSomething() { |
| 368 | <span class="code-keyword">if</span>(m_hello != <span class="code-keyword">null</span>) { |
| 369 | <span class="code-object">System</span>.out.println(m_hello.getMesage()); |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 370 | } |
| 371 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 372 | }</pre> |
| 373 | </div></div> |
| 374 | <p>For this component, metadata should be:</p> |
| 375 | <div class="code"><div class="codeContent"> |
| 376 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 377 | <span class="code-tag"><requires optional=<span class="code-quote">"true"</span>></span> |
| 378 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 379 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 380 | <span class="code-tag"></requires></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 381 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 382 | <span class="code-tag"></component></span></pre> |
| 383 | </div></div> |
| 384 | <p>As for field requirement, the dependency metadata needs to contain |
| 385 | the optional attribute. IPOJO invokes the method only when a 'real' |
| 386 | service is available, so you need to test if m_hello is null before to |
| 387 | use it.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 388 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 389 | <h3><a name="ServiceRequirementHandler-Aggregate&OptionalRequirement"></a>Aggregate & Optional Requirement</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 390 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 391 | <p>A dependency can be both aggregate and optional.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 392 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 393 | <h4><a name="ServiceRequirementHandler-Aggregate&OptionalDependencywithfieldinjection"></a>Aggregate & Optional Dependency with field injection</h4> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 394 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 395 | <div class="code"><div class="codeContent"> |
| 396 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 397 | <span class="code-keyword">private</span> Hello m_hellos[]; |
| 398 | <span class="code-keyword">public</span> doSomething() { |
| 399 | <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.length; i++) { |
| 400 | <span class="code-object">System</span>.out.println(m_hellos[i].getMessage()); |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 401 | } |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 402 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 403 | }</pre> |
| 404 | </div></div> |
| 405 | <p>For this component, metadata could be:</p> |
| 406 | <div class="code"><div class="codeContent"> |
| 407 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 408 | <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> optional=<span class="code-quote">"true"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 409 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 410 | <span class="code-tag"></component></span></pre> |
| 411 | </div></div> |
| 412 | <p>To declare an optional & aggregate field requirement you need to |
| 413 | write the optional attribute in the dependency metadata and to point on |
| 414 | a field array. If no service available, iPOJO injects an empty array.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 415 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 416 | <h4><a name="ServiceRequirementHandler-Aggregate&OptionalRequirementwithmethodinvocation"></a>Aggregate & Optional Requirement with method invocation</h4> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 417 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 418 | <div class="code"><div class="codeContent"> |
| 419 | <pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer { |
| 420 | <span class="code-keyword">private</span> List m_hellos<Hello> = <span class="code-keyword">new</span> ArrayList<Hello>(); |
| 421 | <span class="code-keyword">private</span> void bindHello(Hello h) { m_hellos.add(h); } |
| 422 | <span class="code-keyword">private</span> void unbindHello(Hello h) { m_hellos.remove(h); } |
| 423 | <span class="code-keyword">public</span> <span class="code-keyword">synchronized</span> doSomething() { |
| 424 | <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I < m_hellos.size(); i++) { |
| 425 | <span class="code-object">System</span>.out.println(m_hellos.get(i).getMessage()); |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 426 | } |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 427 | } |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 428 | }</pre> |
| 429 | </div></div> |
| 430 | <p>For this component, metadata could be:</p> |
| 431 | <div class="code"><div class="codeContent"> |
| 432 | <pre class="code-xml"><span class="code-tag"><requires aggregate=<span class="code-quote">"true"</span> optional=<span class="code-quote">"true"</span>></span> |
| 433 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 434 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 435 | <span class="code-tag"></requires></span></pre> |
| 436 | </div></div> |
| 437 | <p>In this case, you need to add the _'aggregate'_attribute and the |
| 438 | _'optional'_attribute. The bindHello and unbindHello will be called |
| 439 | each time a Hello service appears or disappears. These bind / unbind |
| 440 | methods are not called when binding / unbinding a Nullable object (when |
| 441 | both field and method are used).</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 442 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 443 | <h3><a name="ServiceRequirementHandler-FilteredRequirement"></a>Filtered Requirement</h3> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 444 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 445 | <p>A filtered dependency applies an LDAP filter on service provider. |
| 446 | IPOJO reuses OSGi LDAP filter ability. The following metadata |
| 447 | illustrates how to use filters:</p> |
| 448 | <div class="code"><div class="codeContent"> |
| 449 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 450 | <span class="code-tag"><requires filter=<span class="code-quote">"(language=fr)"</span>></span> |
| 451 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 452 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 453 | <span class="code-tag"></requires></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 454 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 455 | <span class="code-tag"></component></span></pre> |
| 456 | </div></div> |
| 457 | <p>To add a filter, just add a 'filter' attribute in your dependency |
| 458 | containing the LDAP filter. iPOJO will select only provider matching |
| 459 | with this filter.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 460 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 461 | <p>Moreover, filters can be customized instance by instance. It is |
| 462 | possible to specialize / change / add the filter of a component in the |
| 463 | instance description. It is useful when you want to create different |
| 464 | instances of the same component, with different filter. To do it, you |
| 465 | have to identify your dependency with an 'id' attribute. Then, you can |
| 466 | adapt the filter of the dependency in the instance description by using |
| 467 | the property "requires.filters". In this property you can specify each |
| 468 | dependency identified by its id and the new value of the filter.</p> |
| 469 | <div class="code"><div class="codeContent"> |
| 470 | <pre class="code-xml"><component |
| 471 | className=<span class="code-quote">"org.apache.felix.ipojo.example.FilteredDependency"</span> |
| 472 | name=<span class="code-quote">"FOO"</span>> |
| 473 | <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> |
| 474 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bind"</span>/></span> |
| 475 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbind"</span>/></span> |
| 476 | <span class="code-tag"></requires></span> |
| 477 | <span class="code-tag"></component></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 478 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 479 | <span class="code-tag"><instance name=<span class="code-quote">"FOO1"</span> component=<span class="code-quote">"FOO"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 480 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 481 | <span class="code-tag"><instance name=<span class="code-quote">"FOO2"</span> component=<span class="code-quote">"FOO"</span>></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 482 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 483 | <span class="code-tag"><property name=<span class="code-quote">"requires.filters"</span>></span> |
| 484 | <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"(foo.property=BAR)"</span>/></span> |
| 485 | <span class="code-tag"></property></span> |
| 486 | <span class="code-tag"></instance></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 487 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 488 | <span class="code-tag"><instance name=<span class="code-quote">"FOO3"</span> component=<span class="code-quote">"FOO"</span>></span> |
| 489 | <span class="code-tag"><property name=<span class="code-quote">"requires.filters"</span>></span> |
| 490 | <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"(foo.property=BAZ)"</span>/></span> |
| 491 | <span class="code-tag"></property></span> |
| 492 | <span class="code-tag"></instance></span></pre> |
| 493 | </div></div> |
| 494 | <p>The FOO component type declares a service dependency with the 'id1' |
| 495 | id. This dependency has no filter by default. The first instance is |
| 496 | just an instance of the FOO component type and does not modify the |
| 497 | dependency. The second one adds a filter to the declared dependency to |
| 498 | target providers with foo.property = BAR. The last one adds another |
| 499 | filter to the declared dependency. By using instance filter |
| 500 | customization, it is possible to create complex applications where you |
| 501 | avoid binding problems by filtering dependencies instance by instance.</p> |
| 502 | |
| 503 | <h3><a name="ServiceRequirementHandler-Targetingaspecificprovider"></a>Targeting a specific provider</h3> |
| 504 | <p>A service dependency can choose a specific provider. To achieve |
| 505 | this, add a 'from' attribute in your requirement description such as in:</p> |
| 506 | <div class="code"><div class="codeContent"> |
| 507 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 508 | <span class="code-tag"><requires from=<span class="code-quote">"MyHelloProvider"</span>></span> |
| 509 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>></span> |
| 510 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>></span> |
| 511 | <span class="code-tag"></requires></span> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 512 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 513 | <span class="code-tag"></component></span></pre> |
| 514 | </div></div> |
| 515 | <p>iPOJO maps the from attribute to a specific filter : |
| 516 | '|(instance.name=MyHelloProvider)(service.pid=MyHelloProvider)'. Then |
| 517 | the dependency can only be fulfilled by a service matching this filter.</p> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 518 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 519 | <p>Moreover, from attributes can be customized instance by instance. It |
| 520 | is possible to specialize / change / add a 'from' attribute of a |
| 521 | component in the instance configuration. It is useful when you want to |
| 522 | create different instances of the same component, with different 'from' |
| 523 | clauses. To do it, you have to identify your dependency with an 'id' |
| 524 | attribute. Then, you can adapt the 'from' of the dependency in the |
| 525 | instance configuration by using the property "requires.from". In this |
| 526 | property you can specify each dependency identified by its id and the |
| 527 | 'from' value.</p> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 528 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 529 | <div class="code"><div class="codeContent"> |
| 530 | <pre class="code-xml"><component |
| 531 | className=<span class="code-quote">"org.apache.felix.ipojo.example.FilteredDependency"</span> |
| 532 | name=<span class="code-quote">"FOO"</span>> |
| 533 | <span class="code-tag"><requires field=<span class="code-quote">"m_foo"</span> id=<span class="code-quote">"id1"</span>></span> |
| 534 | <span class="code-tag"><callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bind"</span>/></span> |
| 535 | <span class="code-tag"><callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbind"</span>/></span> |
| 536 | <span class="code-tag"></requires></span> |
| 537 | <span class="code-tag"></component></span> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 538 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 539 | <span class="code-tag"><instance name=<span class="code-quote">"FOO1"</span> component=<span class="code-quote">"FOO"</span>/></span> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 540 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 541 | <span class="code-tag"><instance name=<span class="code-quote">"FOO2"</span> component=<span class="code-quote">"FOO"</span>></span> |
| 542 | <span class="code-tag"><property name=<span class="code-quote">"requires.from"</span>></span> |
| 543 | <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"myprovider"</span>/></span> |
| 544 | <span class="code-tag"></property></span> |
| 545 | <span class="code-tag"></instance></span> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 546 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 547 | <span class="code-tag"><instance name=<span class="code-quote">"FOO3"</span> component=<span class="code-quote">"FOO"</span>></span> |
| 548 | <span class="code-tag"><property name=<span class="code-quote">"requires.from"</span>></span> |
| 549 | <span class="code-tag"><property name=<span class="code-quote">"id1"</span> value=<span class="code-quote">"myotherprovider"</span>/></span> |
| 550 | <span class="code-tag"></property></span> |
| 551 | <span class="code-tag"></instance></span></pre> |
| 552 | </div></div> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 553 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 554 | <p>The FOO component type declares a service dependency with the 'id1' |
| 555 | id. This dependency has no 'from' attribute by default. The first |
| 556 | instance is just an instance of the FOO component type and does not |
| 557 | modify the dependency. The second one adds a 'from' attribute to the |
| 558 | declared dependency to target the 'myprovider' provider. The last one |
| 559 | adds another 'from' clause to the declared dependency.</p> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 560 | |
| 561 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 562 | <h2><a name="ServiceRequirementHandler-BindingPolicies"></a>Binding Policies</h2> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 563 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 564 | <p>Three binding policies are supported inside iPOJO.</p> |
| 565 | <ul> |
| 566 | <li>Dynamic policy (default): the binding are managed |
| 567 | dynamically. At each injection, the same provider is injected if the |
| 568 | provider is always available. Else a new one is chosen. For aggregate |
| 569 | dependency, the array order does not change; new providers are placed |
| 570 | at the end of the array.</li> |
| 571 | <li>Static policy: the binding is |
| 572 | static. So, once bound a provider cannot disappear. If it disappears, |
| 573 | the instance is invalidated and cannot be revalidated without stopping |
| 574 | and restarting the instance.</li> |
| 575 | <li>Dynamic-priority policy: the |
| 576 | binding is managed dynamically but the injected provider is selected by |
| 577 | using a ranking policy. Two injections can return two different |
| 578 | providers, is a new provider is 'better' than the previous one, despite |
| 579 | the first one is always available. For aggregate dependency, the array |
| 580 | is sorted.</li> |
| 581 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 582 | |
| 583 | |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 584 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 585 | <p>A static binding is declared as following:</p> |
| 586 | |
| 587 | <div class="code"><div class="codeContent"> |
| 588 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 589 | <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> policy=<span class="code-quote">"static"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 590 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 591 | <span class="code-tag"></component></span></pre> |
| 592 | </div></div> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 593 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 594 | <p>A dynamic-priority binding is declared as following:</p> |
| 595 | <div class="code"><div class="codeContent"> |
| 596 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 597 | <span class="code-tag"><requires field=<span class="code-quote">"m_hellos"</span> policy=<span class="code-quote">"dynamic-priority"</span>/></span> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 598 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 599 | <span class="code-tag"></component></span></pre> |
| 600 | </div></div> |
| 601 | <p>By default, the dynamic-priority policy uses the OSGi service |
| 602 | ranking policy. However, it is possible to customize the policy by |
| 603 | adding the '<em>comparator</em>' attribute. This attribute indicates |
| 604 | the class name of a class implementing the java.util.Comparator |
| 605 | interface. IPOJO will create an instance of your comparator and use it |
| 606 | to sort service references (so your customized comparator needs to be |
| 607 | able to sort OSGi Service Reference).</p> |
| 608 | <div class="code"><div class="codeContent"> |
| 609 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...HelloConsumer"</span>></span> |
| 610 | <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> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 611 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 612 | <span class="code-tag"></component></span></pre> |
| 613 | </div></div> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 614 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 615 | <p><a name="ServiceRequirementHandler-nullable"></a></p> |
| 616 | <h2><a name="ServiceRequirementHandler-Noteaboutnullableobject&defaultimplementation"></a>Note about nullable object & default-implementation</h2> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 617 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 618 | <p>The instance implementation can use an optional dependency without |
| 619 | any checking. Indeed, when an instance declares an optional dependency |
| 620 | using field injection, iPOJO create on the fly a Nullable class |
| 621 | implementing the service specification but doing nothing (mock object). |
| 622 | Therefore, iPOJO cannot return a service to the instance, for an |
| 623 | optional dependency, it returns a nullable object.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 624 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 625 | <p>A nullable object returns:</p> |
| 626 | <ul> |
| 627 | <li>Null when the method returns an object</li> |
| 628 | <li>0 when the method returns an int, log, byte, short, char, float or a double</li> |
| 629 | <li>False when the method return a boolean</li> |
| 630 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 631 | |
| 632 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 633 | <p>You can check if the returned object is a nullable object with the test: <em>"myservice instanceof Nullable"</em>.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 634 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 635 | <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> |
| 636 | to check if the service is available. To disable the Nullable pattern, |
| 637 | you need to add the 'nullable="false"' attribute in your service |
| 638 | dependency description as follows:</p> |
| 639 | <div class="code"><div class="codeContent"> |
| 640 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...LogExample"</span>></span> |
| 641 | <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> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 642 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 643 | <span class="code-tag"></component></span></pre> |
| 644 | </div></div> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 645 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 646 | <p>However, you can also indicate a <em>default-implementation</em> for |
| 647 | your optional service. In this case, if no providers are found, iPOJO |
| 648 | creates an instance of the default-implementation and injects it. The |
| 649 | default-implementation attribute describes the class name of your |
| 650 | implementation. The given class <b>MUST</b> implement the required service interface.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 651 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 652 | <p>For example, the following component uses a default implementation for a Log Service dependency:</p> |
| 653 | <div class="code"><div class="codeContent"> |
| 654 | <pre class="code-xml"><span class="code-tag"><component classname=<span class="code-quote">"...LogExample"</span>></span> |
| 655 | <requires field=<span class="code-quote">"m_log"</span> optional=<span class="code-quote">"true"</span> |
Clement Escoffier | 8350751 | 2008-10-13 07:33:03 +0000 | [diff] [blame] | 656 | default-implementation= |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 657 | <span class="code-quote">"org.apache.felix.ipojo.example.default.MyLogService"</span>/> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 658 | ... |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 659 | <span class="code-tag"></component></span></pre> |
| 660 | </div></div> |
| 661 | <p>If the log service is not available, iPOJO creates an object of the |
| 662 | 'org.apache.felix.ipojo.example.default.MyLogService' class. This |
| 663 | object is injected instead of a Nullable object. For instance, the |
| 664 | default implementation can print messages on the System.err stream. The |
| 665 | nullable object does no display anything.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 666 | |
| 667 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 668 | <p><a name="ServiceRequirementHandler-callbacks"></a></p> |
| 669 | <h2><a name="ServiceRequirementHandler-NoteaboutCallbacks"></a>Note about Callbacks</h2> |
| 670 | <p>Dependency manages two type of callback: bind and unbind. A callback |
| 671 | with a type "bind" is called each type that a service provider arrives |
| 672 | and the binding is necessary. According to the cardinality of the |
| 673 | dependency it means:</p> |
| 674 | <ul> |
| 675 | <li>Simple dependency : at the firs binding and at each rebinding to another service provider</li> |
| 676 | <li>Aggregate dependencies: each time that a service provider arrives</li> |
| 677 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 678 | |
| 679 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 680 | <p>An unbind callback is called each time that a <b>used</b> service |
| 681 | provider goes away. For a simple dependency this method is called each |
| 682 | time that the used service provider goes away. For a multiple |
| 683 | dependency this method is called each time that a service provider goes |
| 684 | away.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 685 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 686 | <p>The method can receive in argument the service object or the service |
| 687 | reference (in order to obtain service properties). The bind methods are |
| 688 | delayed since a POJO object is created.</p> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 689 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 690 | <p><a name="ServiceRequirementHandler-discovery"></a></p> |
| 691 | <h2><a name="ServiceRequirementHandler-Noteonserviceinterfacediscovery"></a>Note on service interface discovery</h2> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 692 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 693 | <p>The <tt>specification</tt> attribute is generally optional except |
| 694 | when iPOJO cannot discover the type of the service. iPOJO cannot infer |
| 695 | the type when the dependency has no field and callbacks do not receive |
| 696 | the service object in parameter. In this case, you need to declare the |
| 697 | service interface.</p> |
| 698 | </td> |
| 699 | <td class="confluenceTd" valign="top" width="20%"> |
| 700 | <h6><a name="ServiceRequirementHandler-Overview"></a><b>Overview</b></h6> |
| 701 | <ul> |
| 702 | <li><a href="http://felix.apache.org/site/apache-felix-ipojo.html" title="Apache Felix iPOJO">Home Page</a></li> |
| 703 | <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> |
| 704 | <li><a href="http://felix.apache.org/site/download.html" title="Download">Download & Install </a></li> |
| 705 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 706 | |
| 707 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 708 | <h6><a name="ServiceRequirementHandler-GettingStarted"></a><b>Getting Started</b></h6> |
| 709 | <ul> |
| 710 | <li><a href="http://felix.apache.org/site/ipojo-in-10-minutes.html" title="iPOJO in 10 minutes">iPOJO in 10 minutes</a></li> |
| 711 | <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> |
| 712 | <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> |
| 713 | <li><a href="http://felix.apache.org/site/ipojo-advanced-tutorial.html" title="iPOJO Advanced Tutorial">iPOJO Advanced Tutorial</a></li> |
| 714 | <li><a href="http://felix.apache.org/site/ipojo-composition-tutorial.html" title="iPOJO Composition Tutorial">iPOJO Composition Tutorial</a></li> |
| 715 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 716 | |
| 717 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 718 | <h6><a name="ServiceRequirementHandler-UserGuide"></a><b>User Guide</b></h6> |
| 719 | <ul> |
| 720 | <li><a href="http://felix.apache.org/site/describing-components.html" title="Describing components">Describing components (handler list) </a></li> |
| 721 | <li><a href="http://felix.apache.org/site/using-xml-schemas.html" title="Using XML Schemas">Using XML Schemas</a></li> |
| 722 | <li><a href="http://felix.apache.org/site/apache-felix-ipojo-testing-components.html" title="apache-felix-ipojo-testing-components">Testing components</a></li> |
| 723 | <li><a href="http://felix.apache.org/site/ipojo-advanced-topics.html" title="iPOJO Advanced Topics">Advanced Topics</a></li> |
| 724 | <li><a href="http://felix.apache.org/site/ipojo-faq.html" title="iPOJO FAQ">FAQ</a></li> |
| 725 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 726 | |
| 727 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 728 | <h6><a name="ServiceRequirementHandler-Tools"></a><b>Tools</b></h6> |
| 729 | <ul> |
| 730 | <li><a href="http://felix.apache.org/site/ipojo-eclipse-plug-in.html" title="iPOJO Eclipse Plug-in">iPOJO Eclipse Plug-in</a></li> |
| 731 | <li><a href="http://felix.apache.org/site/ipojo-ant-task.html" title="iPOJO Ant Task">iPOJO Ant Task</a></li> |
| 732 | <li><a href="http://felix.apache.org/site/ipojo-maven-plug-in.html" title="iPOJO Maven Plug-in">iPOJO Maven Plug-in</a></li> |
| 733 | <li><a href="http://felix.apache.org/site/apache-felix-ipojo-junit4osgi.html" title="apache-felix-ipojo-junit4osgi">Junit4OSGi</a></li> |
| 734 | <li><a href="http://felix.apache.org/site/ipojo-concepts-overview.html" title="iPOJO Concepts Overview">iPOJO concepts overview</a></li> |
| 735 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 736 | |
| 737 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 738 | <h6><a name="ServiceRequirementHandler-DeveloperGuide"></a><b>Developer Guide</b></h6> |
| 739 | <ul> |
| 740 | <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> |
| 741 | <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> |
| 742 | <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> |
| 743 | <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> |
| 744 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 745 | |
| 746 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 747 | <h6><a name="ServiceRequirementHandler-Misc&Contact"></a><b>Misc & Contact</b></h6> |
| 748 | <ul> |
| 749 | <li><a href="http://felix.apache.org/site/apache-felix-ipojo-issuestracker.html" title="apache-felix-ipojo-issuestracker">Issues Tracker</a></li> |
| 750 | <li><a href="http://felix.apache.org/site/apache-felix-ipojo-supportedvms.html" title="apache-felix-ipojo-supportedVMs">Supported JVMs</a></li> |
| 751 | <li><a href="http://felix.apache.org/site/apache-felix-ipojo-supportedosgi.html" title="apache-felix-ipojo-supportedOSGi">Supported OSGi Implementations</a></li> |
| 752 | <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> |
| 753 | <li><a href="http://felix.apache.org/site/future-ideas.html" title="Future Ideas">Future Ideas</a></li> |
| 754 | <li><a href="http://felix.apache.org/site/contact.html" title="Contact">Contact</a></li> |
| 755 | <li><a href="http://felix.apache.org/site/related-works.html" title="Related Works">Related Works</a></li> |
| 756 | <li><a href="http://felix.apache.org/site/article-presentations.html" title="Article & Presentations">Article & Presentations</a></li> |
| 757 | </ul> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 758 | |
| 759 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 760 | <hr> |
| 761 | <div class="" align="center"> |
| 762 | <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> |
Clement Escoffier | 6b928e9 | 2008-05-16 20:33:54 +0000 | [diff] [blame] | 763 | |
Clement Escoffier | 8251f60 | 2009-01-15 15:35:17 +0000 | [diff] [blame] | 764 | <script type="text/javascript"> |
| 765 | var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); |
| 766 | document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); |
| 767 | </script><script src="service-requirement-handler_files/ga.js" type="text/javascript"></script> |
| 768 | <script type="text/javascript"> |
| 769 | var pageTracker = _gat._getTracker("UA-1518442-4"); |
| 770 | pageTracker._trackPageview(); |
| 771 | </script> |
| 772 | </td></tr></tbody></table> |
| 773 | </div> |
| 774 | </body></html> |