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">

Lifecycle callbacks

It is often necessary to create a POJO object as soon the instance becomes valid (i.e. required services are available). It is also often needed to be able to stop it nicely. This pages presents the iPOJO capabilities to achieve such actions. iPOJO allows you to invoke methods (callbacks) on the POJO object when instance's state changed. For example, it allows invoking a start method when the instance becomes valid and a stop method when the instance becomes invalid. It allows the creation of immediate component. This page presents how to use this handler.

Div
classtoc
Table of Contents
maxLevel4
minLevel2

Instance Lifecycle

iPOJO instances have a very simple lifecycle. This lifecycle contains two states: INVALID and VALID. Once an instance is created, this instance can only be valid if all its plugged handlers are valid. In the most basic case it means all required services are available. For example, an instance requiring a service (and so using the dependency handler) cannot be valid if the required service is unavailable.

An instance starts and stops in the invalid state.

Image Added

Lifecycle callback

This handler supports two kinds of callback. The INVALID=>VALID callback are invoked when the instance becomes valid (at starting or when an event allows the instance to become valid). The VALID=>INVALID callback are invoked when the instance becomes invalid (at stopping or when an event invalids the instance).

Image Added

An example

Let's take an example. The following class requires a FooService and has two lifecycle callbacks: start and stop.

Code Block

@Component
@Instantiate{html}
h1. Lifecycle callbacks

_It is often necessary to create a POJO object as soon the instance becomes valid. Moreover, it is also often needed to be able to stop it nicely. The lifecycle callback handler allows you invoking methods (callbacks) on the instance when instance's state changed. For example, it allows invoking a {{start}} method when the instance becomes valid and a {{stop}} method when the instance becomes invalid. Moreover, this handler allows the creation of {{immediate}} component. This page presents how to use this handler._

{div:class=toc}
{toc:maxLevel=4|minLevel=2}
{div}

h2. Instance Lifecycle

iPOJO instances have a very simple lifecycle. This lifecycle contains two states: {{INVALID}} and {{VALID}}. Once an instance is created, this instance can only be valid if all its plugged handlers are valid. For example, an instance requiring a service (and so using the dependency handler) cannot be valid if the required service is unavailable. Indeed, the dependency handler will be invalid.

An instance starts and stops in the invalid state.

!lifecycle.png!

h2. Lifecycle callback

This handler supports two kinds of callback. The INVALID=>VALID callback are invoked when the instance becomes valid (at starting or when an event allows the instance to become valid). The VALID=>INVALID callback are invoked when the instance becomes invalid (at stopping or when an event invalids the instance).

!callback.png!

!callbackOnTransition.png!

h2. An example

Let's take an example. The following class requires a FooService and has two lifecycle callbacks: start and stop.
{code}
public class Foo {
              @Requires
              FooService fs;

              @Validate
              private void start() {
                       // Starting method
                       //...
                       fs.foo();
                       //...
                }

                @Invalidate
                protected void stop() {
                        // Stopping method
            			if(fs!=null) { fs.foo(); }
                }
}
{code}
For this class, we define the following component type:
{code:xml}

You can also remove the annotations to use the XML format:

Code Block
xml
xml
<component className="...Foo">
       <requires field="fs"/>
       <callback transition="validate" method="start"/>
       <callback transition="invalidate" method="stop"/>
</component>
<instance component="...Foo"/>

When an instance of this component type is created, the start method is called as soon as the Foo Service (service requirement) becomes available. If the Foo Service is no more available or when the instance is stopped, the stop method is called.

The invoked methods have no argument, but could be private, protected or public. Public methods can be in parent classes too. Moreover, the INVALID=>VALID (validate) method can use service dependencies (the instance becomes valid means that all required services are available); however, in the stop method (invalidate) it is possible that one of these dependency can be null. Indeed, the departure of a service can be the cause of the instance invalidation.

Managing threads

One usage of lifecycle callback is when the instance needs to create threads. Indeed, the thread can be created in the validate callback, and stopped in the invalidate method. The next class shows an example of a class handling a thread by using lifecycle callbacks.

Code Block

@Component
@Instantiate{code}
When an instance of this component type is created, the start method is called as soon as the {{Foo}} Service (service requirement) becomes available. If the {{Foo}} Service is no more available or when the instance is stopped, the stop method is called.

The invoked methods have no argument, but could be private, protected or public. Public methods can be in parent classes too. Moreover, the {{INVALID=>VALID}} (validate) method can use service dependencies (the instance becomes valid means that all required services are available); however, in the stop method (invalidate) it is possible that one of these dependency can be {{null}}. Indeed, the departure of a service can be the cause of the instance invalidation.

h2. Managing threads

One usage of lifecycle callback is when the instance needs to create threads. Indeed, the thread can be created in the validate callback, and stopped in the invalidate method. The next class shows an example of a class handling a thread by using lifecycle callbacks.
{code}
public class HelloRequesterImpl implements Runnable {

    final static int DELAY=10000;

    @Requires
    HelloService\[\] m_hello;&nbsp; // Service Dependency

    boolean end;

    public void run() {
      while (\!end) {
        try {
        synchronized (this) {
          for(int i = 0; i < m_hello.length; i++) {
            System.out.println(m_hello\[i\].sayHello("Clement"));
          }
        }
        Thread.sleep(DELAY);
        } catch (InterruptedException ie) {
             /* will recheck quit */
        }
    }
   }

    @Validate
    public void starting() {
      Thread T = new Thread(this);
      end = false;
      T.start();
}

public void stopping() { end = true; }
{code}
For  this component type,@Invalidate
 the metadata are :
{code:xml}
<component className="... HelloRequesterImpl">
		<requires field="HelloService"/>
		<callback transition="validate" method="starting"/>
		<callback transition="invalidate" method="stopping"/>
</component>
{code}

h2. Invalidate callbacks and services
The invalidate callback has to be developed defensively. Indeed, inside this callback, it might be possible that a service is no more there (the departure of this service has thrown the instance invalidation, which calls the callback). So, you must check that the service is not {{null}} before using it:
{code} public void stopping() { end = true; }

Invalidate callbacks and services

The invalidate callback has to be developed defensively. Indeed, inside this callback, it might be possible that a service is no more there (the departure of this service has thrown the instance invalidation, which calls the callback). So, you must check that the service is not null before using it:

Code Block

@Invalidate
public void stop() {
  if (myservice != null) {
    // you can use the service
  }
  // ...
}
{code}

Thanks

...

to

...

the

...

iPOJO

...

synchronization

...

model,

...

you

...

can

...

be

...

sure

...

that

...

if

...

the

...

service

...

is

...

available,

...

it

...

will

...

be

...

there

...

until

...

the

...

end

...

of

...

the

...

method.

...

Immediate

...

component

...

An

...

instance

...

of

...

an

...

immediate

...

component

...

type

...

is

...

instantiated

...

as

...

soon

...

it

...

becomes

...

valid.

...

It

...

means

...

that,

...

when

...

the

...

instance

...

becomes

...

valid,

...

the

...

constructor

...

of

...

the

...

implementation

...

class

...

is

...

called.

...

This

...

can

...

replace

...

the

...

validate

...

callback.

...

However,

...

it

...

stills

...

a

...

difference

...

between

...

the

...

immediate

...

and

...

the

...

validate

...

callback.

...

The

...

constructor

...

is

...

call

...

only

...

once

...

time.

...

The

...

validate

...

callback

...

is

...

re-called

...

each

...

time

...

the

...

instance

...

becomes

...

valid. Components that do not provide services are automatically set as immediate.

Image Added

To set a component as immediate you must add the immediate attribute to component:

Code Block

@Component(immediate=true)
@Instantiate
public class MyComponent implements MyService {
   // ...
}

However as there is no 'destructor' in Java, the invalidate callback is necessary if some actions are needed when stopping.

Callback on several objects

If you instance has created several objects (called the implementation class constructor several times), the callback is called on each object in the creation order.

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

...