You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Dependency Handler

The dependency handler manage dependency elements. Each dependency element represent a service dependency.

Dependency

A dependency represents a required service. Therefore, it manages the service lookup and the service invocation. The dependency affects directly the component state, and must manage correctly the dynamics of OSGi to allow a complete unloading when a service goes away.

Metadata

Dependency Metadata

The previous image shows you the dependency UML model. A dependency contains 5 information :

  • Field : name of the field reprensenting the dependency in the component class
  • Interface : type of the field
  • Optional : is the dependency an optional dependency ?
  • Filter : filter selecting service provider
  • Callback : allow to call a method on the component instances when a service provider (matching with the dependency) appears or disappears

Some of these attributes are optional (0...1). Indeed, either the component code contains the information; either iPOJO uses a default behaviour.

The field attribute is mandatory. The field attribute contains the name of the field of the component attached with this dependency.

The interface attribute describes the required service. This element is optional because the component implementation contains the same information (the type of the field). If the interface attribute has a value, the consistency of the information is checked.

The optional attribute describes if the dependency is optional or not. An optional dependency is always valid, and does not interact with the component state. On the other hand, when a mandatory is no more valid the component state becomes INVALID.

The filter attribute contains the LDAP request on the service. As default, iPOJO use no filter, but you can specify a filter. For further information, see the OSGi specification.

The callback elements contains the name of method to call when a service provider matching with the dependency appears or disappears. This allow the component to be notified when a service provider arrives or goes away.

Remark that the multiple information on a dependency is not described in the metadata. Indeed, a dependency is set to multiple when the code contains an array. So the HelloService[] m_hello field describe a multiple dependency, but HelloService m_hello describe a simple dependency.

Metadata Examples

XML Metadata

Example 1: <Dependency optional="false" field="m_hello"/> => Mandatory dependency attached to the m_hello field.
Example 2: <Dependency optional="true" field="m_log"/> => Optional Dependency attached to the m_log field
Example 3: <Dependency interface="org.osgi.log.LogService" optional="true" field="m_log"/> => Optional dependency attached to the m_log field, the interface of the service is org.osgi.log.LogService
Example 4: <Dependency filter="(language=fr)" optional="true" field="m_dictionnay"/> => Optional dependency attached to the m_dictionnary field. The language of the needed service need be "fr".

Manifest Metadata

Example 1: Dependency { $optional="true" $field="m_hello"}
Example 2: Dependency { $optional=false $field="m_log"}
Example 3: Dependency { $interface="org.osgi.log.LogService" $optional="true" $field="m_log"}
Example 4: Dependency { $filter="(language=fr)" $optional="true" $\ield="m_dictionnay"}

Technical details on service discovery and service invocation

In fact, the container of the component contains a "Dependencies Manager" managing all the service dependency of the component. To do this, it registers an OSGi service event listener and listens for interesting events. When an interesting service arrives, it stores the service reference. When the service is used, it obtains the service object and returns the object to the component. If it is a multiple dependencies, it returns an array of service object.
When a service goes away, the dependencies manager removes the reference from its list (and call the unget method): the manager does not keep any reference on the old service. This allows a complete unloading of the service.
Two calls to a service can use two different service implementations if the used implementation has gone. iPOJO tries to return always the same service object, since the service goes away.

Note about simple optional dependency

The component implementation can use an optional dependency without any checking. Indeed, when a component declares an optional dependency, iPOJO create on the fly a Nullable class implementing the service specification but doing nothing. Therefore, iPOJO cannot return a service to the component, for an optional dependency, it returns a nullable object.

A nullable object returns:

  • Null when the method returns an object
  • 0 when the method returns an int, log, byte, short, float or a double
  • False when the method return a boolean

You can check if the returned object is a nullable object with the test: _m_myservice instanceof Nullable_

Note about synchronization

When you want to be sure to have always the same service objects, you can use a synchronized block. It is useful for multiple dependencies. Indeed when you want to be sure that a service does not go away during the iteration on your array, you can put your loop inside a synchronized block. Your mutex object should be "this".

Callbacks

Dependency manage two type of callback : bind and unbind. A callback with a type "bind" is called each type that a service provider arrives and the binding is necessary. Following the cardinality of the dependency it means :

  • Simple dependency : at the firs binding and at each rebinding to another service provider
  • Multiple dependency : each time that a service provider arrives
    A callback with the "unbind" type is called each time that a used service provider goes away. For a simple dependency this method is called each time that the used service provider goes away. For a multiple dependency this method is called each time that a service provider goes away.

The method can receive in argument the service object or the service reference (in order to obtain service properties). The bind methods are delayed since a component instance is created.

Limitations

By hiding all the aspect about service discovery and service invocation, we lost some important features:

  • You cannot have the service properties if there is not bind callback with a service reference argument.
  • You cannot change dynamically the filter on a service request.
  • Many works about the synchronization need to be done.
  • No labels