Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Include Page
apache-felix-ipojo-header
apache-felix-ipojo-header

...

HTML

...


<div class="content">

...

Service Dependency Management

One of the main iPOJO feature is the service injection. So, a component can consume a service without managing the service discovery, tracking and binding. iPOJO manages all these interactions and injects required service into the component. This page explains how to use services.

Div
classtoc
Table of Contents
maxLevel4
minLevel2

Service Requirement

What's a service requirement?

A requirement represents a required service. Therefore, it manages the service lookup and the service binding. When an instance requires a service, the handler injects directly a service object inside a field, or invokes a method when a consistent service appears (or disappears). Service requirements can be:

  • Simple / Aggregate : the component can require one or several service providers
  • Mandatory / Optional : a component can declare an optional dependency
  • Filtered : a component can filter available providers
  • Dynamic / Static / Dynamic-Priority : the component can specify the binding policy
  • Specific : the dependency targets a specific service provider
  • Proxy : by default, iPOJO injects a smart proxy, but it can also be a dynamic proxy or the direct references

Dynamism & Instance Lifecycle

In OSGi™, services can appear and disappear dynamically. This implies dependencies can target a provider which can appear or disappear dynamically. So, dependencies need to manage this dynamism by tracking every time available services. At any moment, a dependency can be unresolved (i.e. no more provider can fulfill the requirement). In the case of a mandatory requirement, the instance becomes invalid (an invalid instance is no more accessible externally, for example provided services are unpublished). If a service, resolving the unfilled dependency appears, the instance becomes valid. In consequence, dependencies affect directly the instance state, and must manage correctly OSGi dynamism to allow a complete unloading when a service goes away. As soon a mandatory dependency cannot be fulfilled, the instance is invalidated.

By default, dependencies are managed dynamically (as previously explained). However, iPOJO supports two other types of binding policies:

  • Static : if a bound service disappears, the instance is invalidated and cannot be revalidated (binding broken forever)
  • Dynamic-Priority: at each injection, the best provider is injected, or the providers array is sorted according to the OSGi Ranking policy or to a specified sorting algorithm.

Service Requirement Injection Mechanisms

iPOJO support several types of injections:

  • Field injection: a field contains the service object. As soon as the field is used, a consistent service object is injected. This injection type fully hides the dynamism
    Code Block
    
    @Requires
    private LogService log;
    

...

  • Method invocation:

...

  • when

...

  • a

...

  • service

...

  • appears,

...

  • or

...

  • disappears

...

  • a

...

  • method

...

  • in

...

  • the

...

  • component

...

  • is

...

  • invoked.

...

  • For

...

  • each

...

  • dependency,

...

  • bind

...

  • /

...

  • unbind

...

  • /

...

  • modified

...

  • methods

...

  • are

...

  • invoked

...

  • to

...

  • notify

...

  • the

...

  • component

...

  • of

...

  • the

...

  • event.

...

  • Code Block

...

  • 
    @Bind
    public void bindLogService(LogService log) { /*...*/ }
    @Unbind
    public void unbindLogService(LogService log) { /*...*/ }
    @Modified
    public void modifiedLogService(LogService log) { /*...*/ }
    

...

  • Constructor injection:

...

  • services

...

  • can

...

  • also

...

  • be

...

  • injected

...

  • as

...

  • constructor

...

  • parameter

...

  • (only

...

  • if

...

  • proxies

...

  • are

...

  • enabled).

...

  • 1.7.0-SNAPSHOT

...

  • Code Block

...

  • 
    public MyComponent(@Requires LogService log) { /*...*/ }
    

...

Moreover,

...

the

...

injections

...

types

...

can

...

be

...

mixed.

...

A

...

component

...

can

...

declare

...

a

...

requirement

...

containing

...

both

...

a

...

field

...

and

...

'binding'

...

methods.

...

Field

...

injection

...

Let's

...

imagine

...

a

...

Hello

...

service

...

with

...

one

...

method

...

'getMessage'

...

returning

...

a

...

"Hello

...

Message".

...

The

...

following

...

component

...

implementation

...

can

...

use

...

this

...

service

...

by

...

attaching

...

this

...

service

...

to

...

a

...

field

...

and

...

by

...

using

...

the

...

field:

Code Block
java
java

{code:java}
@Component
@Instantiate
public class HelloConsumer {
    @Requires
    private Hello m_hello;

    public doSomething() {
        System.out.println(m_hello.getMesage());
    }
}
{code}

You

...

can

...

also

...

use

...

XML

...

to

...

describe

...

this

...

component

...

type:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
    <requires field="m_hello"/>
    ...
</component>
{code}

The

...

metadata

...

contains

...

a

...

'requires'

...

element

...

(representing

...

the

...

service

...

dependency)

...

and

...

specify

...

a

...

field

...

used

...

to

...

inject

...

the

...

service.

...

The

...

implementation

...

uses

...

the

...

field

...

as

...

a

...

normal

...

field

...

without

...

managing

...

service

...

interactions.

...

Method

...

invocation

...

The

...

second

...

injection

...

mechanism

...

uses

...

methods

...

in

...

the

...

implementation

...

class.

...

By

...

this

...

way,

...

the

...

dynamics

...

can

...

be

...

managed

...

directly

...

by

...

the

...

developer.

...

Each

...

dependency

...

can

...

declare

...

three

...

methods:

...

  • A

...

  • bind

...

  • method

...

  • called

...

  • when

...

  • a

...

  • service

...

  • appears

...

  • An

...

  • unbind

...

  • method

...

  • called

...

  • when

...

  • a

...

  • service

...

  • disappears

...

  • A

...

  • modified

...

  • method

...

  • called

...

  • when

...

  • a

...

  • service

...

  • is

...

  • modified

...

  • (the

...

  • service

...

  • properties

...

  • changed,

...

  • but

...

  • the

...

  • service

...

  • still

...

  • matches

...

  • the

...

  • requirement)

...

Moreover,

...

callbacks

...

can

...

be

...

in

...

the

...

component

...

super

...

class

...

(in

...

this

...

case

...

methods

...

must

...

be

...

public).

...

These

...

methods

...

can

...

have

...

one

...

of

...

these

...

four

...

signatures:

...

  • Without

...

  • any

...

  • argument:

...

  • the

...

  • method

...

  • is

...

  • just

...

  • a

...

  • notification

...

  • (method())

...

  • With

...

  • the

...

  • service

...

  • object

...

  • :

...

  • the

...

  • object

...

  • is

...

  • the

...

  • implicated

...

  • service

...

  • object

...

  • (method(Service

...

  • svc))

...

  • With

...

  • an

...

  • OSGi

...

  • service

...

  • reference:

...

  • the

...

  • service

...

  • reference

...

  • appearing

...

  • or

...

  • disappearing

...

  • (method(ServiceReference

...

  • ref))

...

  • With

...

  • the

...

  • service

...

  • object

...

  • and

...

  • the

...

  • OSGi

...

  • service

...

  • reference

...

  • (method(Service

...

  • svc,

...

  • ServiceReference

...

  • ref))

...

  • With

...

  • the

...

  • service

...

  • object

...

  • and

...

  • the

...

  • service

...

  • properties

...

  • inside

...

  • a

...

  • Map

...

  • (method(Service

...

  • svc,

...

  • Map

...

  • properties))

...

  • With

...

  • the

...

  • service

...

  • object

...

  • and

...

  • the

...

  • service

...

  • properties

...

  • inside

...

  • a

...

  • Dictionary

...

  • (method(Service

...

  • svc,

...

  • Dictionary

...

  • properties))

...

The

...

following

...

component

...

implementation

...

shows

...

an

...

example

...

of

...

implementation

...

using

...

this

...

mechanism:

Code Block
java
java

{code:java}
@Component
public class HelloConsumer {
  private Hello m_hello;

  @Bind
  public void bindHello(Hello h) { m_hello = h; }
  @Unbind
  public void unbindHello() { m_hello = null; }
  public doSomething() { System.out.println(m_hello.getMesage()); }
}
{code}

The

...

modified

...

callback

...

is

...

not

...

mandatory.

...

The

...

following

...

XML

...

metadata

...

are

...

describing

...

the

...

same

...

component

...

type:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
<requires>
    <callback type="bind" method="bindHello">
    <callback type="unbind" method="unbindHello">
</requires>
...
</component>
{code}

Note,

...

that

...

the

...

different

...

callbacks

...

can

...

be

...

have

...

different

...

signatures.

...

By

...

using

...

this

...

mechanism,

...

you

...

need

...

to

...

be

...

sure

...

to

...

manage

...

the

...

dynamism

...

correctly.

...


(

...

See

...

note

...

on

...

type

...

discovery

...

)

...

Using

...

the

...

@Modified

...

callback

...

is

...

also

...

quite

...

simple:

Code Block
java
java

{code:java}
@Component
public class HelloConsumer {
  private Hello m_hello;

  @Bind
  public void bindHello(Hello h) { m_hello = h; }
  @Unbind
  public void unbindHello() { m_hello = null; }
  @Modified
  public void modifiedHello() { /* ... */ }
  public doSomething() { System.out.println(m_hello.getMesage()); }

}
{code}

h3. Using constructor injection (*

Using constructor injection (1.7.0-SNAPSHOT

...

)

...

Services

...

can

...

also

...

be

...

injected

...

using

...

constructor

...

parameters:

{
Code Block
}
@Component
public class MyComponent {
    private LogService log;

    public MyComponent(@Requires LogService log) {
        this.log = log;
    }
}
{code}

h3. Mixing injections types

The different mechanisms can be used together. In this case, the field receives the value before the bind method invocation. Constructor parameters get their values during the constructor invocation. So, if the field is used in the method, the returned value will be up to date. The following component implementation uses this mechanism:
{code:java}

Mixing injections types

The different mechanisms can be used together. In this case, the field receives the value before the bind method invocation. Constructor parameters get their values during the constructor invocation. So, if the field is used in the method, the returned value will be up to date. The following component implementation uses this mechanism:

Code Block
java
java
public class HelloConsumer {
     @Requires(id="hello")
     private Hello m_hello; // Injected Field

     @Bind(id="hello")
     public void bindHello() { System.out.println("Hello appears"); }
     @Unbind(id="hello")
     public void unbindHello() { System.out.println("Hello disapears"); }

     public doSomething() { System.out.println(m_hello.getMesage()); }
}
{code}
}

In

...

XML,

...

it

...

results

...

in:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
    <requires  field="m_hello">
        <callback type="bind" method="bindHello">
        <callback type="unbind" method="unbindHello">
    </requires>
    ...
</component>
{code}

The {{id}} attribute is used to determine which callbacks 

The id attribute is used to determine which callbacks / fields go together. If ommitted, it is computed automaticcally:

  • for field it uses the field type.
  • for method starting with bind / unbind / modified, it extract the end of the method name (bindFoo => Foo)
  • for constructor parameter, it uses the parameter index

So, it is strongly recommended to specify the id manually.

Injection mechanisms & lazy object creation

iPOJO creates objects only when required. When needed, iPOJO invokes the constructor of the implementation class. The implementation class can use field requirement because values are already injected and obviously constructor parameters. However, method dependencies are called after the constructor. If the service is available before the constructor call, the invocation of the bind methods is delayed until the a component class object is created.

Examples

For all examples both annotations and XML forms are given. Just choose what you'd like to use.

Simple Requirement

By default, a requirement is mandatory, non-filtered and simple (non-aggregate). The previous examples illustrate this kind of dependency. When services goes away and appears, the service substitution is hidden. Fields attached to simple requirement point always a consistent service object. For a simple dependency, the bind method is called once time when the service appears or just after the POJO constructor invocation is the service is available. When the service disappears the unbind method is called. The bind method is re-invoked as soon as another service provider is available. This invocation occurs immediately if another service provider if available. In this case, the instance is not invalidated.

Aggregate Requirement

When a component requires several providers of the same service, it declares an aggregate dependency.

Aggregate Dependency with field injection

Code Block
java
java
/ fields go together. If ommitted, it is computed automaticcally:
* for field it uses the field type.
* for method starting with {{bind}} / {{unbind}} / {{modified}}, it extract the end of the method name ({{bindFoo => Foo}})
* for constructor parameter, it uses the parameter index

So, it is strongly recommended to specify the id manually. 

h3. Injection mechanisms & lazy object creation

iPOJO creates objects only when required. When needed, iPOJO invokes the constructor of the implementation class. The implementation class can use field requirement because values are already injected and obviously constructor parameters. However, method dependencies are called *after* the constructor. If the service is available before the constructor call, the invocation of the bind methods is delayed until the a component class object is created.

h2. Examples

For all examples both annotations and XML forms are given. Just choose what you'd like to use.

h3. Simple Requirement

By default, a requirement is mandatory, non-filtered and simple (non-aggregate). The previous examples illustrate this kind of dependency. When services goes away and appears, the service substitution is hidden. Fields attached to simple requirement point always a consistent service object. For a simple dependency, the bind method is called once time when the service appears or just after the POJO constructor invocation is the service is available. When the service disappears the unbind method is called. The bind method is re-invoked as soon as another service provider is available. This invocation occurs immediately if another service provider if available. In this case, the instance is not invalidated.

h3. Aggregate Requirement

When a component requires several providers of the same service, it declares an aggregate dependency.

h4. Aggregate Dependency with field injection

{code:java}
@Component
public class HelloConsumer {
     @Requires
     private Hello m_hellos[]; // Array => Aggregate
     public doSomething() {
             for(int I = 0; I < m_hellos.length; i++) { 
                 System.out.println(m_hellos[i].getMessage());
             }
       }
}
{code}

For

...

this

...

component,

...

XML

...

metadata

...

could

...

be:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
    <requires field="m_hellos"/>
    ...
</component>
{code}

To

...

declare

...

an

...

aggregate

...

field

...

for

...

field

...

requirement,

...

you

...

only

...

need

...

to

...

declare

...

an

...

array

...

(instead

...

of

...

a

...

scalar

...

type).

...

iPOJO

...

will

...

create

...

and

...

inject

...

the

...

service

...

object

...

array.

...

iPOJO

...

discover

...

that

...

the

...

dependency

...

is

...

aggregate

...

during

...

the

...

bytecode

...

introspection.

...

Array

...

types

...

cannot

...

be

...

'proxied'.

...

Moreover

...

array

...

dependencies

...

cannot

...

be

...

injected

...

as

...

constructor

...

parameter.

{:=
Info
title
Synchronization
}

The

synchronization

is

managed

by

iPOJO.

As

soon

as

you

are

'touching'

a

dependency

in

a

method,

iPOJO

ensure

that

you

will

keep

these

objects

until

the

end

of

the

method.

Nested

methods

will

share

the

same

service

object

set.

Aggregate Dependency with field injection: list, vector, collection and set

It is also possible to inject service objects inside fields of the type:

  • list
  • vector
  • collection
  • set
Code Block
java
java

{info}

h4. Aggregate Dependency with field injection: list, vector, collection and set
It is also possible to inject service objects inside fields of the type:
* list
* vector
* collection
* set

{code:java}
@Component
public class HelloConsumer {
     @Requires(specification="org.apache.felix.ipojo.example.Hello")
     private List<Hello> m_hellos;
     public doSomething() {
             for(Hello h : m_hellos) { 
                 System.out.println(h).getMessage());
             }
       }
}
{code}

For

...

this

...

component,

...

XML

...

metadata

...

could

...

be:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
    <requires field="m_hellos" specification="org.apache.felix.ipojo.example.Hello"/>
    ...
</component>
{code}

In

...

this

...

case,

...

just

...

use

...

the

...

supported

...

type

...

that

...

you

...

want.

...

iPOJO

...

will

...

automatically

...

understand

...

that

...

it

...

is

...

an

...

aggregate

...

dependency,

...

and

...

will

...

create

...

the

...

collection

...

object

...

containing

...

service

...

objects.

...

However,

...

you

...

must

...

specify

...

the

...

service

...

specification.

...

Indeed,

...

generics

...

types

...

cannot

...

be

...

discovered

...

at

...

runtime

...

reliably.

Info
titleService specification discovery

The service specification

{info:title=Service specification discovery} The service specification

(i.e.

interface)

cannot

be

discovered

when

using

these

types

as

the

bytecode

does

not

provide

enough

information.

So,

you

have

to

indicate

the

required

service

interface

(with

the

'specification'

attribute)

in

the

requirement

description.

Info
titleHow iPOJO manage the synchronization for you

As in the previous case, the synchronization is managed by iPOJO. As soon as you are touching a dependency in a method, iPOJO ensure that you will keep these objects until the end of the method. Nested methods will share the same service object set.

Aggregate Dependency with callbacks

Code Block
java
java

{info}

{info:title=How iPOJO manage the synchronization for you}
As in the previous case, the synchronization is managed by iPOJO. As soon as you are _touching_ a dependency in a method, iPOJO ensure that you will keep these objects until the end of the method. Nested methods will share the same service object set.
{info}

h4. Aggregate Dependency with callbacks

{code:java}
public class HelloConsumer {
      private List m_hellos = new ArrayList();
      @Bind(aggregate=true)
      private void bindHello(Hello h) { m_hellos.add(h); }
      @Unbind
      private void unbindHello(Hello h) { m_hellos.remove(h); }
      public synchronized doSomething() {
                  for(Hello h : m_hellos) { 
                    System.out.println(h.getMessage());
                  }
                }
        }
}
{code}

This

...

dependency

...

can

...

also

...

be

...

described

...

in

...

XML

...

as

...

follow:

Code Block
xml
xml

{code:xml}
<requires  aggregate="true">
    <callback type="bind" method="bindHello">
    <callback type="unbind" method="unbindHello">
</requires>
{code}

In

...

this

...

case,

...

iPOJO

...

cannot

...

detect

...

if

...

the

...

dependency

...

is

...

aggregate

...

or

...

not.

...

So,

...

you

...

need

...

to

...

add

...

the

...

'

...

aggregate

...

'

...

attribute.

...

The

...

bindHello

...

and

...

unbindHello

...

will

...

be

...

called

...

each

...

time

...

a

...

Hello

...

service

...

appears

...

or

...

disappears.

{:=
Info
title
Synchronization
}

To

avoid

the

list

modification

during

the

loop,

you

need

synchronized

the

block.

Indeed,

as

the

field

is

not

an

iPOJO

requirement,

iPOJO

will

not

manage

the

synchronization.

{info} h3. Optional Requirement

Optional Requirement (Scalar)

...

An

...

optional

...

requirement

...

does

...

not

...

invalidate

...

the

...

instance

...

despite

...

no

...

providers

...

are

...

available.

...

Moreover,

...

it

...

is

...

possible

...

to

...

inject

...

a

...

default

...

service

...

implementation

...

when

...

no

...

real

...

providers

...

are

...

available.

...

Optional

...

Requirement

...

with

...

field

...

injection

Code Block
java
java


{code:java}
@Component
public class HelloConsumer {
         @Requires(optional=true)
         private Hello m_hello;

         public doSomething() {  
            System.out.println(m_hello.getMesage());  
         }
}
{code}

For

...

this

...

component,

...

equivalent

...

XML

...

metadata

...

could

...

be:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
    <requires field="m_hello" optional="true"/>
    ...
</component>
{code}

To

...

declare

...

an

...

optional

...

requirement,

...

you

...

need

...

to

...

add

...

the

...

'optional'

...

attribute.

...

To

...

avoid

...

null

...

pointer

...

exception,

...

iPOJO

...

injects

...

a

...

Nullable

...

object

...

in

...

the

...

field

...

when

...

no

...

service

...

provider

...

is

...

available.

...

The

...

nullable

...

object

...

implements

...

the

...

service

...

interface,

...

but

...

does

...

nothing.

...

Moreover,

...

it

...

is

...

possible

...

to

...

set

...

a

...

default-implementation

...

for

...

the

...

service.

...

A

...

default-implementation

...

is

...

a

...

class

...

implementing

...

the

...

service

...

but

...

used

...

only

...

when

...

no

...

others

...

service

...

providers

...

are

...

available.

...

The

...

default-implementation

...

object

...

will

...

be

...

injected

...

instead

...

of

...

the

...

Nullable

...

objet.

...

For

...

further

...

information

...

refer

...

to

...

the

...

note

...

about

...

nullable

...

object.

Optional Dependency with callbacks invocation

Code Block
java
java
|#nullable].

h4. Optional Dependency with callbacks invocation

{code:java}
@Component
public class HelloConsumer {
     private Hello m_hello;

     @Bind(optional=true)
     public void bindHello(Hello h) { m_hello = h; }

     @Unbind
     public void unbindHello() { m_hello = null; }

     public doSomething() { 
          if(m_hello != null) { // Must be checked
              System.out.println(m_hello.getMesage()); 
          }
    }
}
{code}

For

...

this

...

component,

...

XML

...

metadata

...

could

...

be:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
<requires optional="true">
    <callback type="bind" method="bindHello">
    <callback type="unbind" method="unbindHello">
</requires>
...
</component>
{code}

As

...

for

...

field

...

requirement,

...

the

...

dependency

...

metadata

...

needs

...

to

...

contain

...

the

...

optional

...

attribute.

...

iPOJO

...

invokes

...

the

...

method

...

only

...

when

...

a

...

'real'

...

service

...

is

...

available,

...

so

...

you

...

need

...

to

...

test

...

if

...

m_hello

...

is

...

null

...

before

...

to

...

use

...

it.

...

Aggregate

...

&

...

Optional

...

Requirement

...

A

...

dependency

...

can

...

be

...

both

...

aggregate

...

and

...

optional.

...

Aggregate

...

&

...

Optional

...

Dependency

...

with

...

field

...

injection

Code Block
java
java


{code:java}
@Component
public class HelloConsumer {
     @Requires(optional=true)
     private Hello m_hellos[];

     public doSomething() {
           for(Hello h : m_hellos) { 
             System.out.println(h.getMessage());
           }
     }
}
{code}

For

...

this

...

component,

...

XML

...

metadata

...

could

...

be:

Code Block
xml
xml

{code:xml}
<component classname="...HelloConsumer">
<requires field="m_hellos" optional="true"/>
...
</component>
{code}

To

...

declare

...

an

...

optional

...

&

...

aggregate

...

field

...

requirement

...

you

...

need

...

to

...

write

...

the

...

optional

...

attribute

...

in

...

the

...

dependency

...

metadata

...

and

...

to

...

point

...

on

...

a

...

field

...

array.

...

If

...

no

...

service

...

available,

...

iPOJO

...

injects

...

an

...

empty

...

array.

...

Aggregate

...

&

...

Optional

...

Requirement

...

with

...

callbacks

Code Block
java
java


{code:java}
@Compoent
public class HelloConsumer {

     private List m_hellos<Hello> = new ArrayList<Hello>();

     @Bind(aggregate=true, optional=true)
     private void bindHello(Hello h) { m_hellos.add(h); }

     @Unbind
     private void unbindHello(Hello h) { m_hellos.remove(h); }

     public synchronized doSomething() {
               for(Hello h : m_hellos) { 
                  System.out.println(h.getMessage());
               }
     }
}
{code}

For

...

this

...

component,

...

XML

...

metadata

...

could

...

be:

Code Block
xml
xml

{code:xml}
<requires aggregate="true" optional="true">
     <callback type="bind" method="bindHello">
     <callback type="unbind" method="unbindHello">
</requires>
{code}

In

...

this

...

case,

...

you

...

need

...

to

...

add

...

the

...

_'aggregate'_attribute

...

and

...

the

...

_'optional'_attribute.

...

The

...

bindHello

...

and

...

unbindHello

...

will

...

be

...

called

...

each

...

time

...

a

...

Hello

...

service

...

appears

...

or

...

disappears.

...

These

...

bind

...

/

...

unbind

...

methods

...

are

...

not

...

called

...

when

...

binding

...

/

...

unbinding

...

a

...

Nullable

...

object

...

(when

...

both

...

field

...

and

...

method

...

are

...

used).

...

Filtered

...

Requirement

...

A

...

filtered

...

dependency

...

applies

...

an

...

LDAP

...

filter

...

on

...

service

...

provider.

...

iPOJO

...

reuses

...

OSGi

...

LDAP

...

filter

...

ability.

...

The

...

following

...

metadata

...

illustrates

...

how

...

to

...

use

...

filters:

{
Code Block
}
@Requires(filter="(language=fr)")
private String DictionaryService dict;
{code}

{code:xml}
Code Block
xml
xml
<requires filter="(language=fr)" field="dict"/>
{code}

To

...

add

...

a

...

filter,

...

just

...

add

...

a

...

'filter'

...

attribute

...

in

...

your

...

dependency

...

containing

...

the

...

LDAP

...

filter.

...

iPOJO

...

will

...

select

...

only

...

provider

...

matching

...

with

...

this

...

filter.

...

When

...

using

...

a

...

filter,

...

you

...

can

...

also

...

use

...

the

...

modified

...

callback

...

invoked

...

when

...

a

...

matching

...

service

...

is

...

modified

...

but

...

still

...

matches

...

the

...

filter:

{
Code Block
}
@Component
public class MyComponent {

    @Bind(filter="(langage=en)")
    public void bindHDictionary(DictionaryService svc) { ... }

    @Unbind
    public void unbindDictionary() { ...}

    @Modified
    public void modifiedDictionary() { ... }

}
{code}

Moreover,

...

filters

...

can

...

be

...

customized

...

instance

...

by

...

instance.

...

It

...

is

...

possible

...

to

...

specialize

...

/

...

change

...

/

...

add

...

the

...

filter

...

of

...

a

...

component

...

in

...

the

...

instance

...

description.

...

It

...

is

...

useful

...

when

...

you

...

want

...

to

...

create

...

different

...

instances

...

of

...

the

...

same

...

component,

...

with

...

different

...

filter.

...

To

...

achieve

...

this

...

customization,

...

you

...

have

...

to

...

identify

...

your

...

dependency

...

with

...

the

...

'id'

...

attribute.

...

Then,

...

you

...

can

...

adapt

...

the

...

filter

...

of

...

the

...

dependency

...

in

...

the

...

instance

...

description

...

by

...

using

...

the

...

property

...

"requires.filters".

...

In

...

this

...

property

...

you

...

can

...

specify

...

each

...

dependency

...

identified

...

by

...

its

...

id

...

and

...

the

...

new

...

value

...

of

...

the

...

filter.

Code Block
xml
xml

{code:xml}
<component 
   className="org.apache.felix.ipojo.example.FilteredDependency">
	<requires field="m_foo" fiter="(foo.property=FOO)" id="id1">
		<callback type="bind" method="bind"/>
		<callback type="unbind" method="unbind"/>
	</requires>
</component>

<instance name="FOO1" component="FOO"/>

<instance name="FOO2" component="FOO">
	<property name="requires.filters">
		<property name="id1" value="(foo.property=BAR)"/>
	</property>
</instance>

<instance name="FOO3" component="FOO">
	<property name="requires.filters">
		<property name="id1" value="(foo.property=BAZ)"/>
	</property>
</instance>
{code}

The

...

component

...

type

...

declares

...

a

...

service

...

dependency

...

with

...

the

...

'id1'

...

id.

...

This

...

dependency

...

has

...

no

...

filter

...

by

...

default.

...

The

...

first

...

instance

...

is

...

just

...

an

...

instance

...

of

...

the

...

FOO

...

component

...

type

...

and

...

does

...

not

...

modify

...

the

...

dependency.

...

The

...

second

...

one

...

adds

...

a

...

filter

...

to

...

the

...

declared

...

dependency

...

to

...

target

...

providers

...

with

...

foo.property

...

=

...

BAR.

...

The

...

last

...

one

...

adds

...

another

...

filter

...

to

...

the

...

declared

...

dependency.

...

By

...

using

...

instance

...

filter

...

customization,

...

it

...

is

...

possible

...

to

...

create

...

complex

...

applications

...

where

...

you

...

avoid

...

binding

...

problems

...

by

...

filtering

...

dependencies

...

instance

...

by

...

instance.

...

Targeting

...

a

...

specific

...

provider

...

A

...

service

...

dependency

...

can

...

choose

...

a

...

specific

...

provider.

...

To

...

achieve

...

this,

...

add

...

a

...

'from'

...

attribute

...

in

...

your

...

requirement

...

description

...

such

...

as

...

in:

{
Code Block
}
@Requires(from="MyHelloProvider")
private Hello m_hello;
{code}

or

...

in

...

XML:

Code Block
xml
xml

{code:xml}
<requires from="MyHelloProvider" field="m_hello"/>
{code}

iPOJO

...

maps

...

the

...

from

...

attribute

...

to

...

a

...

specific

...

filter

...

:

...

'|(instance.name=MyHelloProvider)(service.pid=MyHelloProvider)'.

...

Then

...

the

...

dependency

...

can

...

only

...

be

...

fulfilled

...

by

...

a

...

service

...

matching

...

this

...

filter.

...

Moreover,

...

from

...

attributes

...

can

...

be

...

customized

...

instance

...

by

...

instance.

...

It

...

is

...

possible

...

to

...

specialize

...

/

...

change

...

/

...

add

...

a

...

'from'

...

attribute

...

of

...

a

...

component

...

in

...

the

...

instance

...

configuration.

...

It

...

is

...

useful

...

when

...

you

...

want

...

to

...

create

...

different

...

instances

...

of

...

the

...

same

...

component,

...

with

...

different

...

'from'

...

clauses.

...

To

...

do

...

it,

...

you

...

have

...

to

...

identify

...

your

...

dependency

...

with

...

an

...

'id'

...

attribute.

...

Then,

...

you

...

can

...

adapt

...

the

...

'from'

...

of

...

the

...

dependency

...

in

...

the

...

instance

...

configuration

...

by

...

using

...

the

...

property

...

"requires.from".

...

In

...

this

...

property

...

you

...

can

...

specify

...

each

...

dependency

...

identified

...

by

...

its

...

id

...

and

...

the

...

'from'

...

value.

Code Block
xml
xml


{code:xml}
<component 
   className="org.apache.felix.ipojo.example.FilteredDependency"
   name="FOO">
	<requires field="m_foo" id="id1">
		<callback type="bind" method="bind"/>
		<callback type="unbind" method="unbind"/>
	</requires>
</component>

<instance name="FOO1" component="FOO"/>

<instance name="FOO2" component="FOO">
	<property name="requires.from">
		<property name="id1" value="myprovider"/>
	</property>
</instance>

<instance name="FOO3" component="FOO">
	<property name="requires.from">
		<property name="id1" value="myotherprovider"/>
	</property>
</instance>
{code}

The

...

FOO

...

component

...

type

...

declares

...

a

...

service

...

dependency

...

with

...

the

...

'id1'

...

id.

...

This

...

dependency

...

has

...

no

...

'from'

...

attribute

...

by

...

default.

...

The

...

first

...

instance

...

is

...

just

...

an

...

instance

...

of

...

the

...

FOO

...

component

...

type

...

and

...

does

...

not

...

modify

...

the

...

dependency.

...

The

...

second

...

one

...

adds

...

a

...

'from'

...

attribute

...

to

...

the

...

declared

...

dependency

...

to

...

target

...

the

...

'myprovider'

...

provider.

...

The

...

last

...

one

...

adds

...

another

...

'from'

...

clause

...

to

...

the

...

declared

...

dependency.

...

Binding Policies

Three binding policies are supported inside iPOJO.

  • Dynamic policy (default):

...

  • the

...

  • binding

...

  • are

...

  • managed

...

  • dynamically.

...

  • At

...

  • each

...

  • injection,

...

  • the

...

  • same

...

  • provider

...

  • is

...

  • injected

...

  • if

...

  • the

...

  • provider

...

  • is

...

  • always

...

  • available.

...

  • Else

...

  • a

...

  • new

...

  • one

...

  • is

...

  • chosen.

...

  • For

...

  • aggregate

...

  • dependency,

...

  • the

...

  • array

...

  • order

...

  • does

...

  • not

...

  • change;

...

  • new

...

  • providers are placed at the end of the array.
  • Static policy: the binding is static. So, once bound a provider cannot disappear. If it disappears, the instance is invalidated and cannot be revalidated without stopping and restarting the instance.
  • Dynamic-priority policy: the binding is managed dynamically but the injected provider is selected by using a ranking policy. Two injections can return two different providers, is a new provider is 'better' than the previous one, despite the first one is always available. For aggregate dependency, the array is sorted.

A static binding is declared as following:

Code Block
 are placed at      the end of the array.
* Static policy: the binding is static. So, once      bound a provider cannot disappear. If it disappears, the instance is      invalidated and cannot be revalidated without stopping and restarting the      instance.
* Dynamic-priority policy: the binding is managed      dynamically but the injected provider is selected by using a ranking      policy. Two injections can return two different providers, is a new      provider is 'better' than the previous one, despite the first one is always      available. For aggregate dependency, the array is sorted.


A static binding is declared as following:
{code}
@Requires(policy="static")
private Hello[] m_hellos;
{code}
or
{code:xml}

or

Code Block
xml
xml
<requires field="m_hellos" policy="static"/>
{code}

A

...

dynamic-priority

...

binding

...

is

...

declared

...

as

...

following:

{
Code Block
}
@Requires(policy="dynamic-priority")
private Hello[] m_hellos;
{code}
or
{code:

or

Code Block
xml
xml
xml}
<requires field="m_hellos" policy="dynamic-priority"/>
{code}

By

...

default,

...

the

...

dynamic-priority

...

policy

...

uses

...

the

...

OSGi

...

service

...

ranking

...

policy.

...

However,

...

it

...

is

...

possible

...

to

...

customize

...

the

...

policy

...

by

...

adding

...

the

...

'

...

comparator

...

'

...

attribute.

...

This

...

attribute

...

indicates

...

the

...

class

...

name

...

of

...

a

...

class

...

implementing

...

the

...

java.util.Comparator

...

interface.

...

iPOJO

...

creates

...

an

...

instance

...

of

...

your

...

comparator

...

and

...

uses

...

it

...

to

...

sort

...

service

...

references

...

(so

...

your

...

customized

...

comparator

...

needs

...

to

...

be

...

able

...

to

...

sort

...

OSGi

...

Service

...

Reference).

{
Code Block
}
@Requires(policy="dynamic-priority", comparator=MyComparator.class)
private Hello[] m_hellos;
{code}

or

Code Block
xml
xml
or
{code:xml}
<requires field="m_hellos" policy="dynamic-priority" comparator="great.MyComparator"/>
{code}

{anchor:nullable}
h2. Note about nullable object & default-implementation

The instance implementation can use an optional dependency without any checking. Indeed, when an instance declares an optional dependency using field injection, iPOJO create on the fly a Nullable class implementing the service specification but doing nothing (mock object). Therefore, iPOJO cannot return a service to the instance, 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, char, 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: _"myservice instanceof Nullable"_.

You can disable the Nullable pattern too (activated by default). In this case, iPOJO injects {{null}} instead of a _Nullable_ object. So, you can just test if your field is equals to _null_ to check if the service is available. To disable the Nullable pattern, you need to add the 

Anchor
nullable
nullable

Note about nullable object & default-implementation

The instance implementation can use an optional dependency without any checking. Indeed, when an instance declares an optional dependency using field injection, iPOJO create on the fly a Nullable class implementing the service specification but doing nothing (mock object). Therefore, iPOJO cannot return a service to the instance, 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, char, 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: "myservice instanceof Nullable".

You can disable the Nullable pattern too (activated by default). In this case, iPOJO injects null instead of a Nullable object. So, you can just test if your field is equals to null to check if the service is available. To disable the Nullable pattern, you need to add the 'nullable="false"'

...

attribute

...

in

...

your

...

service

...

dependency

...

description

...

as

...

follows:

{
Code Block
}
@Requires(optional=true, nullable=false)
private LogService m_log;
{code}
or
{code:xml

or

Code Block
xml
xml
}
 <requires field="m_log" optional="true" nullable="false"/>
{code}

However,

...

you

...

can

...

also

...

indicate

...

a

...

default-implementation

...

for

...

your

...

optional

...

service.

...

In

...

this

...

case,

...

if

...

no

...

providers

...

are

...

found,

...

iPOJO

...

creates

...

an

...

instance

...

of

...

the

...

default-implementation

...

and

...

injects

...

it.

...

The

...

default-implementation

...

attribute

...

describes

...

the

...

class

...

name

...

of

...

your

...

implementation.

...

The

...

given

...

class

...

MUST

...

implement

...

the

...

required

...

service

...

interface.

...

For

...

example,

...

the

...

following

...

component

...

uses

...

a

...

default

...

implementation

...

for

...

a

...

Log

...

Service

...

dependency:

{
Code Block
}
@Requires(optional=true, default-implementation=MyLogService.class)
private LogService m_log;

or

Code Block
xml
xml
{code}
or
{code:xml}
<requires field="m_log" optional="true" 
    default-implementation=
       "org.apache.felix.ipojo.example.default.MyLogService"/>
{code}

If

...

the

...

log

...

service

...

is

...

not

...

available,

...

iPOJO

...

creates

...

an

...

object

...

of

...

the

...

'org.apache.felix.ipojo.example.default.MyLogService'

...

class.

...

This

...

object

...

is

...

injected

...

instead

...

of

...

a

...

Nullable

...

object.

...

For

...

instance,

...

the

...

default

...

implementation

...

can

...

print

...

messages

...

on

...

the

...

System.err

...

stream.

...

The

...

nullable

...

object

...

does

...

no

...

display

...

anything.

...

Anchor
callbacks
callbacks

Note about Callbacks

Dependency manages 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. According to the cardinality of the dependency it means:

  • Simple dependency : at the firs binding and at each rebinding to another service provider
  • Aggregate dependencies: each time that a service provider arrives

An unbind callback 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 POJO object is created.

Proxies

Since iPOJO 1.6, iPOJO injects proxy objects. Those proxies are by default smart proxies and are design to be lightweight:

  • for scalar requirement : the service object is a proxy
  • for aggregate dependencies : iPOJO injects a smart collections

The goal of the proxies is to hide the dynamism and more particularly the dynamism. So, you can gives a service dependency to another object, using the service object still supports the dynamism. For collections, you can iterate over the collection without managing the potential departures and arrivals of services. The proxy also manage that the component class and the delegate objects shared the same services is they are accessed in the same Thread.

By default iPOJO injects proxy except for arrays. Moreover, it is possible to disable the proxy injection by adding proxy=false to the requires element (or to the @Requires and @Bind annotations). It is also possible to inject dynamic proxies (if the platform does not support dynamically generated classes). To enable dynamic proxies, set the system or bundle property ipojo.proxy.type to dynamic-proxy. You can also disable completely the proxy injection by setting the system property ipojo.proxy to disabled.

Anchor
discovery
discovery

Note on service interface discovery

The specification attribute is generally optional except when iPOJO cannot discover the type of the service. iPOJO cannot infer the type when the dependency has no field and callbacks do not receive the service object in parameter. In this case, you must the service specification (i.e. interface).

Include Page
apache-felix-ipojo-footer
apache-felix-ipojo-footer