How to use iPOJO annotations¶
You can use annotations to define your component types. This page presents supported annotations.
Getting iPOJO Annotations:¶
iPOJO Annotations are defines inside the org.apache.felix.ipojo.annotations project
. You can download the Jar file of this project from the download page. Sources are available on the [Felix trunk|http://felix.apache.org/site/sourcecode.html].
Once added to your class path / build path / dependencies, you can use the annotations as normal annotations. These annotations are automatically processed by the iPOJO manipulator, and do not need to be deployed at runtime.
With Eclipse (or any other IDE)¶
Add the org.apache.felix.ipojo.annotations jar file in your build path. Do not forget to use a Java compiler accepting annotations (1.5 or higher).
With Maven¶
Add the following dependency:
<dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.ipojo.annotations</artifactId> <version>1.12.1</version> </dependency>
Moreover, you need to set that the source code and the target code are Java 1.5 code. To achieve this, just add the following plugin in your plugins section:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin>
With Ant¶
Just add the org.apache.felix.ipojo.annotations jar file in your class path.
An example of usage¶
To illustrate annotations usage, let taking the tutorial example. In this tutorial, there are two components: The first one provides the hello service The second one uses the provided hello service You can download the archive containing the examples and a preconfigured version of Felix here.
Hello Service Provider¶
The provider uses two annotations. The "component" annotation is mandatory and defines that the class defines a component type. Then the "provides" annotation just declare that the defined component type provides a service.
package ipojo.example.hello.impl; import ipojo.example.hello.Hello; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Provides; /** * Component implementing the Hello service. **/ @Component @Provides public class HelloImpl implements Hello { public String sayHello(String name) { return "hello " + name; } }
Hello Service Consumer¶
The Hello Service Consumer use more annotations. First it used the component annotation. To defines its "immediate" behavior, it add the 'immediate' attribute. Then, it uses the requires annotation to define a service dependency. Finally, it uses the validate and invalidate annotations to define lifecycle callbacks.
package ipojo.example.hello.client; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Invalidate; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.Validate; import ipojo.example.hello.Hello; @Component(name="AnnotatedHelloClient", immediate=true) @Instantiate public class HelloClient implements Runnable { @Requires private Hello[] m_hello; private final static int DELAY=10000; private boolean end; public void run() { while (!end) { try { invoke(); Thread.sleep(DELAY); } catch (InterruptedException ie) { } } } public void invoke() { for (int i = 0; i < m_hello.length; i++) { System.out.println(m_hello[i]. sayHello("iPOJO")); } } @Validate public void starting() { Thread thread = new Thread(this); end = false; thread.start(); } @Invalidate public void stopping() { end = true; } }
Defined Annotations¶
This section lists defined annotations and how to use them.
@Component¶
Goal: Defines a component type Target: The component implementation class Attributes:
- name : defines the component type name (optional, default = the class name)
- immediate: defines the component type as immediate (optional, default = "false")
- architecture: enable the architecture exposition (optional, default = "false")
- propagation: enable configuration property propagation (on provided services) (optional, default = "false")
- managedservice : set the Managed Service PID. (optional, default = no PID (i.e. the managed service will not be exposed)).
- factoryMethod : set the factory-method. The specified method must be a static method and return a pojo object.(optional, default = iPOJO uses the 'regular' constructor).
- publicFactory : set if the component type is public. (optional, default = true).
@Provides¶
Goal: Defines that the component type provide services Target: The component implementation class Attributes:
- specifications: defines the provided interface (optional, default = all implemented interfaces)
- strategy : the service object creation strategy. Possible values : SINGLETON, SERVICE, METHOD, INSTANCE or the strategy class name. With SINGLETON there is only one POJO per component instance, SERVICE means OSGi Service factory, METHOD delegates the creation to the factory-method of the component, INSTANCE creates one service object per requiring instance. For other strategies, specify the qualified name of the CreationStrategy class. (optional, default = SINGLETON)
- properties : array containing
@StaticServiceProperties
defining service properties not attached to fields.
The SERVICE strategy refers to the OSGi service factory. So, one service object per asking bundle will be created.
@Requires¶
Goal: Defines a service dependency Target: Field, Constructor Parameter Attributes:
- filter: defines the LDAP filter (optional)
- optional: defines if the dependency is optional (optional, default = "false")
- id: defines the dependency Id (useful to identify bind & unbind methods) (optional, default = field name) (if a dependency with the same id is already created (by a @bind or @unbind annotation), it merges the dependencies).
- nullable: enable or disable the Null Object injection when the dependency is optional and no providers are available (optional, default = "true")
- defaultimplementation: set the Default-Implmentation (optional, by default iPOJO uses a Null object)
- exception : the class of the runtime exception to throw when no service providers are available
- policy: defines the binding policy (optional)
- comparator: defines the comparator to use to sort service references (optional, default = OSGi Service Reference Comparator)
- from : defines the specific provider to use
- specification : the required service specification. This attribute is required for Collection field. (optional, default = annotated field type).
- proxy : enables / disables the proxy injection (enabled by default)
- timeout : the timeout ins millisecond to wait before applying the no service action
@ServiceProperty¶
Goal: Defines a service property Target: Field Attributes:
- name: property name (optional, default=field name
- value: property value (optional, default=no value)
- mandatory : is the property mandatory? (optional, default=false)
A mandatory property must receive a value either from the component type description (value attribute), or the instance configuration.
@ServiceController¶
Goal: Control the service exposition Target: Field (Boolean) Attributes:
- value : the default value. If set to false, it disables the initial exposition
- specification : set the target of the controller, must be an exposed service interface. By default, the controller targets all services.
@Property¶
Goal: Defines a property Target: Field, Method, Constructor Parameter Attributes:
- name: property name (optional, default=field name computed by removing "set" from the method name (for instance setFoo(String ff) will get the Foo name), the argument name for constructor injection)
- value: property value (optional, default=no value)
- mandatory : is the property mandatory? (optional, default=false)
If another property with the same name is defined, the method or field or constructor argument is added to the existing property.
@Updated¶
Goal: Defines method called when a reconfiguration is completed. Target: a method (receiving a dictionary in argument)
@Bind¶
Goal: Defines a bind method Target: Method Attributes:
- Id: Dependency Id, if the id is already defines in a "@requires " or "@unbind" annotation, it adds this method as a bind method of the already created dependency. (optional, default= no id, compute an id if the method name begin by "bind" (for instance "bindFoo" will have the "Foo" id))
- Specification : required dependency (optional)
- Aggregate : is the dependency an aggregate dependency (optional, default= "false")
- Optional: is the dependency an optional dependency (optional, default= "false")
- Filter: dependency LDAP filter (optional)
- Policy: defines the binding policy (optional)
- Comparator: defines the comparator to use to sort service references (optional, default = OSGi Service Reference Comparator)
- From : defines the specific provider to use
@Unbind¶
Goal: Defines an unbind method Target: Method Attributes:
- Id: Dependency Id, if the id is already defines in a "@requires" or "@bind" annotation, it adds this method as an unbind method of the already created dependency. (optional, default= no id, compute an id if the method name begin by "unbind" (for instance "unbindFoo" will have the "Foo" id))
- Specification : required dependency (optional)
- Aggregate : is the dependency an aggregate dependency (optional, default= "false")
- Optional: is the dependency an optional dependency (optional, default= "false")
- Filter: dependency LDAP filter (optional)
- Policy: defines the binding policy (optional)
- Comparator: defines the comparator to use to sort service references (optional, default = OSGi Service Reference Comparator)
- From : defines the specific provider to use
@Modified¶
Goal: Defines an modified
method, called when a bound service is udpated.
Target: Method
Attributes:
- Id: Dependency Id, if the id is already defines in a "@requires" or "@bind" annotation, it adds this method as an unbind method of the already created dependency. (optional, default= no id, compute an id if the method name begin by "unbind" (for instance "unbindFoo" will have the "Foo" id))
- Specification : required dependency (optional)
- Aggregate : is the dependency an aggregate dependency (optional, default= "false")
- Optional: is the dependency an optional dependency (optional, default= "false")
- Filter: dependency LDAP filter (optional)
- Policy: defines the binding policy (optional)
- Comparator: defines the comparator to use to sort service references (optional, default = OSGi Service Reference Comparator)
- From : defines the specific provider to use
@Validate¶
Goal: defines a validate lifecycle callback Target: method
@Invalidate¶
Goal: defines a validate lifecycle callback Target: method
@PostRegistration¶
Goal: defines a callback invoked after service registration. The callback must have the following signature : public void name(ServiceReference ref)
Target: method
@PostUnregistration¶
Goal: defines a callback invoked after service unregistration. The callback must have the following signature : public void name(ServiceReference ref)
Target: method
@Instantiate¶
Goal: declare a simple instance (this is equivalent to <instance component="..."></instance>
Target: class
Attribute:
- name: the instance name (optional)
Temporal Dependencies (external handler)¶
The temporal dependency handler is an external handler. However, it can be used with an annotation defined in the iPOJO annotations jar file.
The annotation is org.apache.felix.ipojo.handler.temporal.Requires
and targets a field.
Attributes:
- filter : specify the dependency filter
- timeout : specify the dependency timeout (optional)
- onTimeout : specify the onTimeout action (null, nullable, empty-array, default-implementation (specify the class name in this case) (optional).
- specification : the required service specification. This attribute is required for Collection field. (optional, default = annotated field type).
- proxy : Inject a proxy instead of the real object. This allows passing this reference to collaborators. (Default = false)
Exposing instances as a JMX MBean (external handler)¶
The JMX Handler allows exposing an instance as a JMX MBean. To configure the JMX handler directly from your code, three annotations are provided. They are in the org.apache.felix.ipojo.handlers.jmx
package
The @org.apache.felix.ipojo.handlers.jmx.Config
(@Config
if the package it correctly imported) annotation is a type annotation (so placed on the class
element. This annotation indicates that the instance will be exposed as an MBean. This annotation supports:
- usesMOSGi: set to
true
to use MOSGi. Otherwise, the MBean will be exposed in the MBean Platform Server (default:false
). - objectname: set the MBean objectname. The objectname must follow JMX specification. (default:
package-name:factory-name:instance-name
) - domain: set the MBean domain. (default:
package-name
) - name: set the MBean name. (default:
instance-name
).
The @org.apache.felix.ipojo.handlers.jmx.Property
(@Property
) annotation is a field annotation indicating that the field is exposed in the MBean. The supported attributes are:
- name: set the property name
- rights: set the access permission. Possible values are
r
(read only) andw
(read and write). By default, properties are in read-only mode. - notification: enables notification on this property. By default notifications are disabled.
The @org.apache.felix.ipojo.handlers.jmx.Method
(@Method
) annotation is a method annotation indicating that the method is exposed in the MBean. Only one attribute can be customized:
- description: set the method description.
Advanced topics and FAQ¶
Metadata file and annotation merge¶
It is possible to defines component type both in the metadata file (in XML) and by using annotation. However, if a component type defined by using annotations has the same name than a type define in the XML file, the XML descriptor override the annotation defined type. However, a warning message is launched during the manipulation.
Instance creation¶
The @Instantiate annotation allows creating an instance, but this declaration is limited:
- it does not support configuration
- it does not allow naming
- the instance is created in the global scope (so no composition)
To define instances, you should use the XML descriptor. Instance can refer to annotated types by referring to their names.
<instance component="ipojo.example.hello.impl.HelloImpl"/> <instance component="AnnotedHelloClient"/>
Using Custom Annotations¶
External handlers can provides their own annotations. Using these annotations just requires to add them to your build path. To external handlers annotations, please refer to the external handler documentation.