SeamFramework.orgCommunity Documentation

Chapter 4. Weld-OSGi addressing event notification and comunication

4.1. Get OSGi event notifications in your bean bundles
4.2. Use your own inter bundle notifications

Weld-OSGi is enabling CDI in bean bundles, so you can use CDI event notification in your bean bundles. But Weld-OSGi also provide the support of OSGi framework events through CDI event mechanisms. And following the same principle Weld-OSGi also allows a full uncouple communication between bean bundles based on CDI events.

In this chapter you will see:

From here you will create a new application based on bean bundles. So far your bundles were greeting and saying goodbye, let them be a bit more interactive. You will have three bean bundles that present themselves when they start and greet newcomers (and say goodbye to leavers) when they start (or stop).

Create your three bean bundles following this scheme. They will be the welcoming-tom, welcoming-dick and welcoming-harry bean bundles.

First write the com.sample.App main classes:

package com.sample;

import org.osgi.cdi.api.extension.events.BundleContainerEvents;
import org.osgi.cdi.api.extension.events.BundleEvents;

import javax.enterprise.event.Observes;

public class App {

    public void onStartup(@Observes BundleContainerEvents.BundleContainerInitialized event) { (1)
        System.out.println("Tom: Hi everyone!");
    }

    public void onShutdown(@Observes BundleContainerEvents.BundleContainerShutdown event) { (2)
        System.out.println("Tom: Bye everyone!");
    }

    public void greetNewcomer(@Observes BundleEvents.BundleStarted event) { (3)
        String name = event.getSymbolicName().substring(21, event.getSymbolicName().length()); (4)
        if (!name.equals("tom")) { (5)
            System.out.println("Tom: Welcome " + name +'!');
        }
    }

    public void sayGoodbyeToLeaver(@Observes BundleEvents.BundleStopped event) { ((6)
        String name = event.getSymbolicName().substring(21, event.getSymbolicName().length()); (7)
        if (!name.equals("tom")) { (8)
            System.out.println("Tom: Goodbye " + name +'!');
        }
    }
}

You monitor four different Weld-OSGi events, two events about the CDI life cycle (your entry point from the previous chapter) (1) (2) an two events about the bundle life cycle (from the OSGi framework) (3) (6). It allows to perform actions when the bean bundle is started (both for OSGi and CDI point of view) (1) or stopped (2). Here you just greet or say goodbye. When a bundle (every bundle) starts (3) or stops (6) you get its name (4) (7) and say the appropriate sentence to other bundle (5) (8). Do not forget to change the name accordingly to the current bundle !

Now configure your three bean bundles:

Your three projects should now looks like that:

welcoming-*
      pom.xml
    - src
        - main
            - java
                - com.sample
                  App.java
            - resources
                - META-INF
                  beans.xml
                  welcoming-*.bnd

Try everything out:

You can now use inter bundle notification in order to make your bean bundles aware of the other bundles. But the choice of events seems a bit limited, more or less is about bundle (and bean bundle) and service life cycle. But what if you want to fire and listen custom events ?

Weld-OSGi allows it with its InterBundleEvent events. In this section you will update your three bean bundles to make them chat even when no movement is occurring. For example your bean bundles can ask if the others are still here on regular basis.

Update your three bean bundles following this scheme. They will be the talkative-tom, talkative-dick and talkative-harry bean bundles.

Update the com.sample.App main classes:

package com.sample;

import org.osgi.cdi.api.extension.annotation.Sent;
import org.osgi.cdi.api.extension.annotation.Specification;
import org.osgi.cdi.api.extension.events.BundleContainerEvents;
import org.osgi.cdi.api.extension.events.BundleEvents;
import org.osgi.cdi.api.extension.events.InterBundleEvent;
import org.osgi.framework.Bundle;

import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.inject.Inject;

public class App {

    @Inject
    private Event<InterBundleEvent> communication; (1)

    public void onStartup(@Observes BundleContainerEvents.BundleContainerInitialized event) { (2)
        System.out.println("Harry: Hi everyone!");
        AskThread askThread = new AskThread(communication, event.getBundleContext().getBundle()); (3)
        askThread.start();
    }

    public void onShutdown(@Observes BundleContainerEvents.BundleContainerShutdown event) { (4)
        System.out.println("Harry: Bye everyone!");
    }

    public void greetNewcomer(@Observes BundleEvents.BundleStarted event) { (5)
        String name = event.getSymbolicName().substring(21, event.getSymbolicName().length());
        if (!name.equals("harry")) {
            System.out.println("Harry: Welcome " + name + '!');
        }
    }

    public void sayGoodbyeToLeaver(@Observes BundleEvents.BundleStopped event) { (6)
        String name = event.getSymbolicName().substring(21, event.getSymbolicName().length());
        if (!name.equals("harry")) {
            System.out.println("Harry: Goodbye " + name + '!');
        }
    }

    public void acknowledge(@Observes @Sent @Specification(String.class) InterBundleEvent message) { (7)
        System.out.println("Harry: Hey " + message.get() + " i'm still here.");
    }

    private class AskThread extends Thread { (8)
        Event<InterBundleEvent> communication;
        Bundle bundle;

        AskThread(Event<InterBundleEvent> communication, Bundle bundle) {
            this.communication = communication;
            this.bundle = bundle;
        }

        public void run() {
            while(true) { (9)
                try {
                    sleep(5000);
                } catch (InterruptedException e) {
                }
                if(bundle.getState() == Bundle.ACTIVE) { (10)
                    System.out.println("Harry: is there still someone here ?");
                    communication.fire(new InterBundleEvent("harry")); (11)
                } else {
                    break;
                }
            }
        }
    }
}

There is no modification for the previous chat action (2) (4) (5) (6); except that you start a thread when the bean bundle has started (3). This thread (8) is an infinite loop (9) that ask the active bundle to acknowledge there presence by firing an InterBundleEvent (11). This InterBundleEvent is listened by your three bean bundles in order to print the answer. The listening method catch only communication from outside the bean bundle (@Sent) and that has a String message (@Specification(String.class)) (7).

There is nothing to update in the bean bundles configuration files.

Your three projects should now looks like that:

talkative-*
      pom.xml
    - src
        - main
            - java
                - com.sample
                  App.java
            - resources
                - META-INF
                  beans.xml
                  talkative-*.bnd

Install everything and let your bundle chat:

____________________________
Welcome to Apache Felix Gogo

g! lb
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (3.2.2)
    1|Active     |    1|Apache Felix Bundle Repository (1.6.2)
    2|Active     |    1|Apache Felix Gogo Command (0.8.0)
    3|Active     |    1|Apache Felix Gogo Runtime (0.8.0)
    4|Active     |    1|Apache Felix Gogo Shell (0.8.0)
    5|Active     |    1|Weld-OSGi :: Core :: Extension Impl (1.0.0.SNAPSHOT)
    6|Active     |    1|Weld-OSGi :: Implementation :: Weld Integration (1.0.0.SNAPSHOT)
    7|Resolved   |    1|Weld-OSGi :: Core :: Extension API (1.0.0.SNAPSHOT)
    8|Resolved   |    1|Weld-OSGi :: Core :: Integration API (1.0.0.SNAPSHOT)
    9|Resolved   |    1|Weld-OSGi :: Core :: Mandatory (1.0.0.SNAPSHOT)
   10|Installed  |    1|talkative-dick (1.0.0)
   11|Installed  |    1|talkative-harry (1.0.0)
   12|Installed  |    1|talkative-tom (1.0.0)
g! start 10 11 12
Dick: Hi everyone!
Harry: Hi everyone!
Dick: Welcome harry!
Tom: Hi everyone!
Dick: Welcome tom!
Harry: Welcome tom!
g! Dick: is there still someone here ?
Harry: Hey dick i'm still here.
Tom: Hey dick i'm still here.
Harry: is there still someone here ?
Dick: Hey harry i'm still here.
Tom: Hey harry i'm still here.
Tom: is there still someone here ?
Dick: Hey tom i'm still here.
Harry: Hey tom i'm still here.
Dick: is there still someone here ?
Harry: Hey dick i'm still here.
Tom: Hey dick i'm still here.
Harry: is there still someone here ?
Dick: Hey harry i'm still here.
Tom: Hey harry i'm still here.
Tom: is there still someone here ?
Dick: Hey tom i'm still here.
Harry: Hey tom i'm still here.
stop 10
Dick: Bye everyone!
Tom: Goodbye dick!
Harry: Goodbye dick!
g! stop 11
Harry: Bye everyone!
Tom: Goodbye harry!
g! stop 12
Tom: Bye everyone!
g! 

You can play with your bean bundles, looking them chat with each other. The InterBundleEvent allow you to fire any object you want, so it is a powerful communication system between your bean bundle. You may refer to the Weld-OSGi specifications for a complete review of InterBundleEvent usage.