iPOJO using annotations

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.

Overview

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.

Beginner's annotations

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.

@Component

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:

  • name: Optional definition of the component name, defaults to the class name if not set
  • immediate: Optionally tag this component as requiring to be created as soon as it has all its requirements met. It is true, by default, when the component does not provide a service. Otherwise it defaults to false. An immediate component is dealt with an eager instantiation mechanism; while a non-immediate component follows a lazy instantiation mechanism (instantiated when first needed).

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.

@Provides

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:

  • strategy: Defines the instantiation strategy (or policy) for the provided service. Its default value is:
    • SINGLETON, meaning that a single instance of the service is shared among the components that require it

      Other values are:

      • INSTANCE, specifying that a separate instance is created per component that requires it
      • SERVICE, refers to the OSGi service factory
      • METHOD, refers to one of the component methods as a factory method

@Requires

It annotates a class field and declares it as a dependency requiring injection.

Some attributes of interest are:

  • optional: Specifies if the field assignment is optional. It's default value is true
  • nullable: Allows the Null object injection when the dependency is not available. Its default value is false.

@ServiceProperty

It annotates a field of a component providing a service and exposes it as a service property.

Its attributes are all optional:

  • name: Provides a name for the property, defaults to the field name
  • value: Provides a value for the property. Otherwise, a value must be provided along with the instance declaration
  • mandatory: Specifies if the property is mandatory (that is, a value is required for it) and is false by default

@Property

It annotates a field or a method and registers an internal property of the component.

Its attributes are as follows:

  • name: Provides a name for the property, defaults to the bean name. For example, if this annotation is attached to a field, then the default name is the field name. If the annotation is attached to a setter of a field, for example, setMyField(), then the name of the property would be MyField
  • value: Provides a value for the property. Otherwise, a value must be provided along with the instance declaration
  • mandatory: Specifies if the property is mandatory (that is, a value is required for it) and is false by default

Tip

The difference between a @Property and a @serviceProperty is its visibility to other services: properties are internal to the component, while service properties are made visible to external components.

@Instantiate

It requests the addition of an instance declaration along with the component declaration. This is a slightly limited replacement of the<instance /> element in the configuration. It annotates the component class and does not take data parameters.

Instantiating annotated components

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.253.210