felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Felix > Apache Felix Dependency Manager - Using Annotations - Components
Date Mon, 07 Feb 2011 21:07:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2036/9/1/_/styles/combined.css?spaceKey=FELIX&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Dependency+Manager+-+Using+Annotations+-+Components">Apache
Felix Dependency Manager - Using Annotations - Components</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~pderop">Pierre
De Rop</a>
    </h4>
        <br/>
                         <h4>Changes (2)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>* *provides*: By default,
the component is registered into the OSGi registry under all directly implemented interfaces.
If no interfaces are implemented, then the component is not registered, but it still has a
managed lifecycle, and may have some dependencies. If you need to  explicitly define the list
of interfaces (or classes) under which the  component must be registered in the OSGi registry,
then use the _provides_ attribute. You can also set this property to an empty array of classes
 if you don&#39;t want at all your component to be exposed in the OSGi  registry (even
if it implements some interfaces). <br></td></tr>
            <tr><td class="diff-unchanged" >* *properties*: enumerates the list
of properties that are part of the Service exposed by the component in the OSGi Registry.
Each property is defined using the @Property annotation, which represents a  key/value pair.
When a value is actually an array of strings, then the _values_ attribute of the @Property
annotation can be used. This attribute  is not the only way to specify OSGi Service properties
(see Setting Service properties in the lifecycle section). <br></td></tr>
            <tr><td class="diff-unchanged" >* *factoryMethod*: may match a static
method name from the annotated class which can be used to instantiate the component instance.
Normally, DependencyManager instantiates the component using its class name, and with the
default constructor of the class, but there are some cases where it is required to take control
of  how the component is created. For instance, this method may be used to create the component
as a dynamic proxy ... <br></td></tr>
            <tr><td class="diff-unchanged" >* *factorySet*: The component factory
ID. By default, a component is automatically instantiated as a singleton when the bundle is
started, and when all required dependencies are satisfied. But when a component must be created,
configured, or disposed dynamically, and when multiple instances of the same component are
needed, a factorySet should  be used. When you use this attribute, a java.util.Set&lt;Dictionary&gt;
 object is registered into the OSGi regitry, with a specific *{_}dm.factory.name{_}* property
matching the ID you specify in the attribute. This Set&lt;Dictionary&gt; will act
as a Factory API, and another component may define a dependency on this Set and add some configuration
dictionaries in  it, in order to fire some component instantiation/activation. There is one
component instantiated per added dictionary, which is passed to component instances via a
configurable callback method (using the *{_}factoryConfigure{_}* attribute). All public properties
will be propagated  along with eventual published service. A public property is a property
 which does not start with a dot (&quot;.&quot;). Properties starting with a dot are
considered private to the component, and won&#39;t be propagated to published service.
This model is actually similar to the Declarative Service &quot;Component Factories&quot;
concept, except that you don&#39;t have a dependency on a specific API, but rather on
a basic jdk class  (java.util.Set&lt;Dictionary&gt;). Notice that, unlike in Declarative
Service, the component factory is provided once the component bundle is started, even if required
dependencies are not satisfied. This is useful when the component want  to dynamically configure
its dependency filters. So, to summarize: <br>** Each time a new Dictionary is added
into the Set, then a new instance of the annotated component will be instantiated, and this
dictionary is passed to the component callback specified with the factoryConfigure attribute.
<br>** Each time an existing Dictionary is re-added into the Set, then the corresponding
component instance is updated, and the updated dictionary is also passed to the callback specified
in the factoryConfigure attribute. <br>** Each time an existing Dictionary is removed
from the Set, then the  corresponding component instance will be stopped and destroyed. <br></td></tr>
            <tr><td class="diff-unchanged" >* *factoryConfigure*: Sets the &quot;configure&quot;
method name to be called with the factory configuration. This attribute only makes sense if
the factorySet() attribute is used. If specified, then this attribute references a component
callback method, which is called for providing the configuration supplied by the factory that
instantiated this component. The current Service properties will be also updated with all
public properties (which don&#39;t start with a dot). <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>* *ranking*: Sets the ranking
of this aspect. Since aspects are chained, the ranking defines the order in which they are
chained. Chain ranking is implemented as a service ranking so service lookups automatically
retrieve the top of the chain. <br></td></tr>
            <tr><td class="diff-unchanged" >* *service*: Sets the service interface
to apply the aspect to. By default, the directly implemented interface is used. <br></td></tr>
            <tr><td class="diff-unchanged" >* *filter*: Sets the filter condition
to use with the service interface this aspect is applying to. <br></td></tr>
            <tr><td class="diff-unchanged" >* *properties*: Sets Additional properties
to use with the aspect service registration. <br></td></tr>
            <tr><td class="diff-unchanged" >* *field*: Sets the field name where
to inject the original service. By default, the original service is injected in any attributes
in the aspect implementation that are of the same type as the aspect interface. <br></td></tr>
            <tr><td class="diff-unchanged" >* *factoryMethod*: Sets the static
method used to create the AspectService implementation instance. The default constructor of
the annotated class is used. The factoryMethod can be used to provide a specific aspect implements,
like a DynamicProxy. <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h2. @AdapterService <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Adapters,
like with @AspectService, are used to &quot;extend&quot; existing services, and can
publish different services based on the existing one. An example would be implementing a management
interface for an existing service, etc .... When you annotate an adapter class with the @AdapterService
annotation, it will be applied to any service that matches the implemented interface and filter.
The adapter will be registered with the specified interface and existing properties from the
original service plus any extra properties you supply here. If you declare the original service
as a member it will be injected.  <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Annotation
attributes: <br> <br>* *adapteeService*: Sets the adaptee service interface this
adapter is applying to. <br>* *provides*: Sets the adapter service interface(s). By
default, the directly implemented interface(s) is (are) used.  <br>* *properties*: Sets
some additional properties to use with the adapter service registration. By default, the adapter
will inherit all adaptee service properties. <br>* *adapteeFilter*: Sets the filter
condition to use with the adapted service interface. <br>* *factoryMethod*: Sets the
static method used to create the adapter service implementation instance. By default, the
default constructor of the annotated class is used. <br> <br>Usage example: Here,
the AdapterService is registered into the OSGI registry each time an AdapteeService is found
from the registry. The AdapterImpl class adapts the AdapteeService to the AdapterService.
The AdapterService will also have a service property (param=value), and will also include
eventual service properties found from the AdapteeService: <br> <br>{code} <br>
@AdapterService(adapteeService = AdapteeService.class, properties={@Property(name=&quot;param&quot;,
value=&quot;value&quot;)}) <br> class AdapterImpl implements AdapterService
{ <br>     // The service we are adapting (injected by reflection) <br>     protected
AdapteeService adaptee; <br> <br>     public void doWork() { <br>      
 adaptee.mehod1(); <br>        adaptee.method2(); <br>     } <br> } <br>{code}
<br> <br></td></tr>
            <tr><td class="diff-unchanged" >h2. @BundleAdapterService <br>
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h1><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-AnnotationsWritingComponents"></a>Annotations
- Writing Components</h1>


<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-ComponentTypes"></a>Component
Types</h2>

<p>Before diving into all annotations, we must first introduce the  different types
of components DependencyManager is supporting. In  Dependency Manager, you may use the following
types of components,  depending on what you need:</p>


<ul>
	<li><b>Component</b>: Components are the main building blocks for OSGi
applications. They can publish themselves as a service, and/or they can have dependencies.
These dependencies will influence their life cycle as component will only be activated when
all required dependencies are available.</li>
</ul>


<ul>
	<li><b>Aspect Service</b>: A service that provides a non-functional aspect
on top of an existing service. In aspect oriented programming, an aspect, or interceptor can
sit between a client and another target service used by the client. An Aspect Service first
tracks a target service and is created once the target service is detected. Then the Aspect
Service is provided, but with a higher  ranking, and the client is transparently updated with
the aspect. Aspects can be chained and may apply to the same target service (and in this case,
the ranking of the Aspect service is used to chain aspects in  the proper order).</li>
</ul>


<ul>
	<li><b>Adapter Service</b>: A Service that adapts another existing service
into a new one. Like with aspects, sometimes you want to create adapters for certain services,
which add certain behavior that results in the publication of (in this case) a different service.
Adapters can dynamically be added and removed and allow you to keep your basic services implementations
clean and simple, adding extra features on top of them in a modular way.</li>
</ul>


<p>Now we have introduced the different types of components, here is the list of annotations,
allowing to declare DependencyManager service components:</p>

<ul>
	<li><b>@Component:</b> for declaring a Component that eventually publishes
a singleton OSGi service as long as its dependencies are resolved.</li>
	<li><b>@AspectService</b>: provides a non-functional aspect on top of an
existing service.</li>
	<li><b>@AdapterService</b>: creates an OSGi service that adapts another
existing service into a new interface.</li>
	<li><b>@BundleAdapterService</b>: creates an OSGi service a service on
top of a given bundle.</li>
	<li><b>@ResourceAdapterService</b>: creates an OSGi service on top of a
specific Resource.</li>
	<li><b>@FactoryConfigurationAdapterService</b>: creates an OSGi service
from ConfigAdmin, using a factoryPid, and a ManagedServiceFactory.</li>
</ul>


<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-@Component"></a>@Component</h2>

<p>This annotation annotates an implementation class that optionally publishes an OSGi
service, and optionally has some dependencies, with a managed lifecycle. The annotation has
the following attributes:</p>

<ul>
	<li><b>provides</b>: By default, the component is registered into the OSGi
registry under all directly implemented interfaces. If no interfaces are implemented, then
the component is not registered, but it still has a managed lifecycle, and may have some dependencies.
If you need to  explicitly define the list of interfaces (or classes) under which the  component
must be registered in the OSGi registry, then use the <em>provides</em> attribute.
You can also set this property to an empty array of classes  if you don't want at all your
component to be exposed in the OSGi  registry (even if it implements some interfaces).</li>
	<li><b>properties</b>: enumerates the list of properties that are part
of the Service exposed by the component in the OSGi Registry. Each property is defined using
the @Property annotation, which represents a  key/value pair. When a value is actually an
array of strings, then the <em>values</em> attribute of the @Property annotation
can be used. This attribute  is not the only way to specify OSGi Service properties (see Setting
Service properties in the lifecycle section).</li>
	<li><b>factoryMethod</b>: may match a static method name from the annotated
class which can be used to instantiate the component instance. Normally, DependencyManager
instantiates the component using its class name, and with the default constructor of the class,
but there are some cases where it is required to take control of  how the component is created.
For instance, this method may be used to create the component as a dynamic proxy ...</li>
	<li><b>factorySet</b>: The component factory ID. By default, a component
is automatically instantiated as a singleton when the bundle is started, and when all required
dependencies are satisfied. But when a component must be created, configured, or disposed
dynamically, and when multiple instances of the same component are needed, a factorySet should
 be used. When you use this attribute, a java.util.Set&lt;Dictionary&gt;  object is
registered into the OSGi regitry, with a specific <b><em>dm.factory.name</em></b>
property matching the ID you specify in the attribute. This Set&lt;Dictionary&gt;
will act as a Factory API, and another component may define a dependency on this Set and add
some configuration dictionaries in  it, in order to fire some component instantiation/activation.
There is one component instantiated per added dictionary, which is passed to component instances
via a configurable callback method (using the <b><em>factoryConfigure</em></b>
attribute). All public properties will be propagated  along with eventual published service.
A public property is a property  which does not start with a dot ("."). Properties starting
with a dot are considered private to the component, and won't be propagated to published service.
This model is actually similar to the Declarative Service "Component Factories" concept, except
that you don't have a dependency on a specific API, but rather on a basic jdk class  (java.util.Set&lt;Dictionary&gt;).
Notice that, unlike in Declarative Service, the component factory is provided once the component
bundle is started, even if required dependencies are not satisfied. This is useful when the
component want  to dynamically configure its dependency filters. So, to summarize:
	<ul>
		<li>Each time a new Dictionary is added into the Set, then a new instance of the annotated
component will be instantiated, and this dictionary is passed to the component callback specified
with the factoryConfigure attribute.</li>
		<li>Each time an existing Dictionary is re-added into the Set, then the corresponding
component instance is updated, and the updated dictionary is also passed to the callback specified
in the factoryConfigure attribute.</li>
		<li>Each time an existing Dictionary is removed from the Set, then the  corresponding
component instance will be stopped and destroyed.</li>
	</ul>
	</li>
	<li><b>factoryConfigure</b>: Sets the "configure" method name to be called
with the factory configuration. This attribute only makes sense if the factorySet() attribute
is used. If specified, then this attribute references a component callback method, which is
called for providing the configuration supplied by the factory that instantiated this component.
The current Service properties will be also updated with all public properties (which don't
start with a dot).</li>
</ul>


<p>Usage example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
 /**
   * This component will be activated once the bundle is started and when all required dependencies
   * are available.
   */
 @Component
 class X <span class="code-keyword">implements</span> Z {
     @ConfigurationDependency(pid=<span class="code-quote">"MyPid"</span>)
     void configure(Dictionary conf) {
          <span class="code-comment">// Configure or reconfigure our service.
</span>     }

     @Start
     void start() {
         <span class="code-comment">// Our component is starting and is about to be
registered in the OSGi registry as a Z service.
</span>     }

     <span class="code-keyword">public</span> void doService() {
         <span class="code-comment">// ...
</span>     }
 }

</pre>
</div></div>
<p>Example using a factorySet, where the X component is instantiated/updated/disposed
by another Y component:</p>


<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @Component(factorySet=<span class="code-quote">"MyComponentFactory"</span>,
factoryConfigure=<span class="code-quote">"configure"</span>)
  class X <span class="code-keyword">implements</span> Z {
      void configure(Dictionary conf) {
          <span class="code-comment">// Configure or reconfigure our component. The
conf is provided by the factory,
</span>          <span class="code-comment">// and all <span class="code-keyword">public</span>
properties (which don't start with a dot) are propagated with the
</span>          <span class="code-comment">// Service properties eventually specified
in the properties annotation attribute.
</span>      }

      @ServiceDependency
      void bindOtherService(OtherService other) {
          <span class="code-comment">// store <span class="code-keyword">this</span>
require dependency
</span>      }

      @Start
      void start() {
          <span class="code-comment">// Our component is starting and is about to be
registered in the OSGi registry as a Z service.
</span>      }

      <span class="code-keyword">public</span> void doService() {
          <span class="code-comment">// ... part of Z <span class="code-keyword">interface</span>
</span>      }
  }

  /**
    * This class will instantiate some X component instances
    */
  @Component
  class Y {
      @ServiceDependency(filter=<span class="code-quote">"(dm.factory.name=MyComponentFactory)"</span>)
      Set&lt;Dictionary&gt; _XFactory; <span class="code-comment">// This Set
acts as a Factory API <span class="code-keyword">for</span> creating X component
instances.
</span>
      @Start
      void start() {
          <span class="code-comment">// Instantiate a X component instance
</span>          Dictionary x1 = <span class="code-keyword">new</span> Hashtable()
{{ put(<span class="code-quote">"foo"</span>, <span class="code-quote">"bar1"</span>);
}};
          _XFactory.add(x1);

          <span class="code-comment">// Instantiate another X component instance
</span>          Dictionary x2 = <span class="code-keyword">new</span> Hashtable()
{{ put(<span class="code-quote">"foo"</span>, <span class="code-quote">"bar2"</span>);
}};
          _XFactory.add(x2);

          <span class="code-comment">// Update the first X component instance
</span>          x1.put(<span class="code-quote">"foo"</span>, <span
class="code-quote">"bar1_modified"</span>);
          _XFactory.add(x1);

          <span class="code-comment">// Destroy all components (Notice that invoking
_XFactory.clear() also destroys every X instances)
</span>          _XFactory.remove(x1);
          _XFactory.remove(x2);
      }
  }
</pre>
</div></div>

<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-@AspectService"></a>@AspectService</h2>

<p>Aspects allow you to define an interceptor, or chain of interceptors for a service
(to add features like caching or logging, etc ...). The dependency manager intercepts the
original service, and allows you to execute some code before invoking the original service
... The aspect will be applied to any service that matches the specified interface and filter
and will be registered with the same interface and properties as the original service, plus
any extra properties you supply here. It will also inherit all dependencies, and if you declare
the original service as a member it will be injected.</p>

<p>Annotation attributes:</p>

<ul>
	<li><b>ranking</b>: Sets the ranking of this aspect. Since aspects are
chained, the ranking defines the order in which they are chained. Chain ranking is implemented
as a service ranking so service lookups automatically retrieve the top of the chain.</li>
	<li><b>service</b>: Sets the service interface to apply the aspect to.
By default, the directly implemented interface is used.</li>
	<li><b>filter</b>: Sets the filter condition to use with the service interface
this aspect is applying to.</li>
	<li><b>properties</b>: Sets Additional properties to use with the aspect
service registration.</li>
	<li><b>field</b>: Sets the field name where to inject the original service.
By default, the original service is injected in any attributes in the aspect implementation
that are of the same type as the aspect interface.</li>
	<li><b>factoryMethod</b>: Sets the static method used to create the AspectService
implementation instance. The default constructor of the annotated class is used. The factoryMethod
can be used to provide a specific aspect implements, like a DynamicProxy.</li>
</ul>


<p>Usage example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
 @AspectService(ranking=10), properties={@Property(name=<span class="code-quote">"param"</span>,
value=<span class="code-quote">"value"</span>)})
 class AspectService <span class="code-keyword">implements</span> InterceptedService
{
     <span class="code-comment">// The service we are intercepting (injected by reflection)
</span>     <span class="code-keyword">protected</span> InterceptedService
intercepted;
   
     <span class="code-keyword">public</span> void doWork() {
        intercepted.doWork();
     }
 }
</pre>
</div></div>

<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-@AdapterService"></a>@AdapterService</h2>

<p>Adapters, like with @AspectService, are used to "extend" existing services, and can
publish different services based on the existing one. An example would be implementing a management
interface for an existing service, etc .... When you annotate an adapter class with the @AdapterService
annotation, it will be applied to any service that matches the implemented interface and filter.
The adapter will be registered with the specified interface and existing properties from the
original service plus any extra properties you supply here. If you declare the original service
as a member it will be injected. </p>

<p>Annotation attributes:</p>

<ul>
	<li><b>adapteeService</b>: Sets the adaptee service interface this adapter
is applying to.</li>
	<li><b>provides</b>: Sets the adapter service interface(s). By default,
the directly implemented interface(s) is (are) used.</li>
	<li><b>properties</b>: Sets some additional properties to use with the
adapter service registration. By default, the adapter will inherit all adaptee service properties.</li>
	<li><b>adapteeFilter</b>: Sets the filter condition to use with the adapted
service interface.</li>
	<li><b>factoryMethod</b>: Sets the static method used to create the adapter
service implementation instance. By default, the default constructor of the annotated class
is used.</li>
</ul>


<p>Usage example: Here, the AdapterService is registered into the OSGI registry each
time an AdapteeService is found from the registry. The AdapterImpl class adapts the AdapteeService
to the AdapterService. The AdapterService will also have a service property (param=value),
and will also include eventual service properties found from the AdapteeService:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
 @AdapterService(adapteeService = AdapteeService.class, properties={@Property(name=<span
class="code-quote">"param"</span>, value=<span class="code-quote">"value"</span>)})
 class AdapterImpl <span class="code-keyword">implements</span> AdapterService
{
     <span class="code-comment">// The service we are adapting (injected by reflection)
</span>     <span class="code-keyword">protected</span> AdapteeService adaptee;
   
     <span class="code-keyword">public</span> void doWork() {
        adaptee.mehod1();
        adaptee.method2();
     }
 }
</pre>
</div></div>

<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-@BundleAdapterService"></a>@BundleAdapterService</h2>


<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-@ResourceAdapterService"></a>@ResourceAdapterService</h2>


<h2><a name="ApacheFelixDependencyManager-UsingAnnotations-Components-@FactoryConfigurationAdapterService"></a>@FactoryConfigurationAdapterService</h2>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Dependency+Manager+-+Using+Annotations+-+Components">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=23335750&revisedVersion=8&originalVersion=7">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Dependency+Manager+-+Using+Annotations+-+Components?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message