An alternative way of tagging components for iPOJO is to annotate them directly in the Java code. iPOJO provides annotations support through the org.apache.felix.ipojo.annotations
library.
There are some gains in clarity of the code when using annotations and it also simplifies updates by keeping the configuration closer to its target class or field.
For instance, in the previous declaration of the bookshelf service, we could have replaced the configuration entry in the meta.xml
file:
<component classname= "com.packtpub.felix.bookshelf.service.impl.BookshelfServiceImpl" name="BookshelfServiceImpl"> <provides /> <requires field="inventory" /> </component>
With annotations to the class BookshelfServiceImpl:
@Component(name="BookshelfServiceImpl") @Provides public class BookshelfServiceImpl implements BookshelfService { @Requires BookInventory inventory;
Which would have the same effect.
Let's quickly go through the main annotations of interest; the others are left for you to check online through the available iPOJO documentation (http://felix.apache.org/site/how-to-use-ipojo-annotations.html).
As a general rule, when declaring components both as annotations and in XML, the XML takes precedence. This is a common pitfall, where one would want to move to annotations but forget to remove the declarations from the XML configuration file, thus getting unexpected results.
It annotates an implementation class and is used to declare it as a component type (that is, a factory). The classname
attribute is not available here as it is the class that's annotated. Some of the attributes of interest here are as follows:
The other attributes are a bit more advanced, but I recommend you go online and read about them when you get more comfortable using annotations.
It annotates an implementation class and is used to declare it as a component that provides a service.
Among the available attributes, one of interest is:
Other values are:
It annotates a field or a method and registers an internal property of the component.
Its attributes are as follows:
setMyField()
, then the name of the property would be MyField
The separation between the component declaration and the instantiation is an important separation of concerns. The idea is very close to the class/instance relationship; components can be considered as types, or factories, and the instance is an occurrence of this component.
Items that apply to the type definition and behavior are defined at the level of the component, while others, such as the setting of property values, are related to the instance.
This is one of the reasons why the @Instantiate
annotation does not allow naming or configuration.
The best practice is to define the instance of the component outside of the component definition; thus allowing the added flexibility of configuring different instances in different ways. Items such as properties and service properties can be configured either in the instance declaration or using the Config Admin service.
When both configuration and annotation based declarations are found by iPOJO, the configuration based declaration takes precedence in the shaping of a component.