Ouertani Slim was born in Tunisia in 1981. Now he is a software engineer since 2004 and he is Java 6 and Spring certified with 100% and 94% respectively. He is very interested in Java technology, Scala and open source projects. He believes that programming is one of the hardest jobs and most beautiful in the world. Slim has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

OSGi : PostEvent vs SendEvent in New Thread

09.27.2009
| 19760 views |
  • submit to reddit
This post show the difference between postEvent and sendEvent in osgi throw in example. According to documentation, post initiate asynchronous delivery of an event and send is the synchronous one.

But, what is the difference between postEvent and new Thread{ void run(){sendevent}}? This post outline this difference using some examples.

Introduction

The example consist on two bundles:

1- The first, for sending post and send event every 10 seconds, on two different queues.
2- The second, register two EventHanlers for each queue and print a received msg after 30 seconds.

The Notifier Bundle

The activator bundle send and post events using two different threads  using ServiceTracker for EventAdmin service :
@Override
public void start(BundleContext bundleContext) throws Exception {
eventAdminTracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
eventAdminTracker.open();
eventAdmin = (EventAdmin) eventAdminTracker.getService();
if (eventAdmin != null) {
new Thread() {

@Override
public void run() {
try {
postEvent();
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();


new Thread() {

@Override
public void run() {
try {
sendEvent();
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();

}

postEvent() and sendEvent() are identical except they use two different queues. The first one use postEvent  and the second one sendEvent methods of EventAdmin. Messages will be sent every 10 s containing the current sending time.

postEvent sendEvent
private static final String POST_EVENT_QUEUE = "JTUNSIE/post";
private void postEvent() throws InterruptedException {
Dictionary props = new Properties();
int i = 0;
while (true) {
Date d = new Date();
props.put("property", "" + i++ + " : " + d);
System.out.println("before post : " + d);
Event event = new Event(POST_EVENT_QUEUE, props);
eventAdmin.postEvent(event);
System.out.println("after post : " + d);
Thread.sleep(10 * 1000);
}
}
private static final String SEND_EVENT_QUEUE = "JTUNSIE/send";
private void sendEvent() throws InterruptedException {
Dictionary props = new Properties();
int i = 0;
while (true) {
Date d = new Date();
props.put("property", "" + i++ + " : " + d);
System.out.println("before send ; " + d);
Event event = new Event(SEND_EVENT_QUEUE, props);
eventAdmin.sendEvent(event);
System.out.println("after send : " + d);
Thread.sleep(10 * 1000);
}
}

The Handler Bundle

Noting special here. The handler bundle register two EventHandlers one for the POST_EVENT_QUEUE and the other for SEND_EVENT_QUEUE. They wait for 30 s processing messages before printing it's time content.
public class PostEventHandler implements EventHandler{

@Override
public void handleEvent(Event event) {
String value = event.getProperty("property").toString();
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("---------------->Post value : " + value);

}

}

public class SendEventHandler implements EventHandler{

@Override
public void handleEvent(Event event) {
String value = event.getProperty("property").toString();
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException ex) {
Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("---------------->Send value : " + value);

}

}

public class Activator implements  BundleActivator {

private static final String POST_EVENT_QUEUE = "JTUNSIE/post";
private static final String SEND_EVENT_QUEUE = "JTUNSIE/send";



@Override
public void start(BundleContext context) throws Exception {
Dictionary dp = new Hashtable();
dp.put(EventConstants.EVENT_TOPIC, POST_EVENT_QUEUE);
Dictionary ds = new Hashtable();
ds.put(EventConstants.EVENT_TOPIC, SEND_EVENT_QUEUE);

context.registerService(EventHandler.class.getName(), new PostEventHandler(), dp);
context.registerService(EventHandler.class.getName(), new SendEventHandler(), ds);
}

@Override
public void stop(BundleContext context) throws Exception {
}
}

Result

This is the console output :

before post : Sat Sep 26 12:39:30 CEST 2009
before send ; Sat Sep 26 12:39:30 CEST 2009
after post : Sat Sep 26 12:39:30 CEST 2009

osgi> before post : Sat Sep 26 12:39:40 CEST 2009
after post : Sat Sep 26 12:39:40 CEST 2009
before post : Sat Sep 26 12:39:50 CEST 2009
after post : Sat Sep 26 12:39:50 CEST 2009
---------------->Post value : 0 : Sat Sep 26 12:39:30 CEST 2009
before post : Sat Sep 26 12:40:00 CEST 2009
after post : Sat Sep 26 12:40:00 CEST 2009
---------------->Send value : 0 : Sat Sep 26 12:39:30 CEST 2009
after send : Sat Sep 26 12:39:30 CEST 2009
before post : Sat Sep 26 12:40:10 CEST 2009
after post : Sat Sep 26 12:40:10 CEST 2009
before send ; Sat Sep 26 12:40:10 CEST 2009

We remark that the send method is waiting to print "after send" until the handler process the message  meaning that the sender still waiting the reciever. The post method is the best solution to  deliver asynchronous event without waiting handler with immediate return.

Difference Between postEvent and sendEvent Using Thread

According to specification cnmp version 4.2 paragraph 113.7.2 page 352 :
Asynchronous event delivery is initiated by the postEvent method. When
this method is invoked, the Event Admin service must determine which
handlers are interested in the event. By collecting this list of handlers during
the method invocation, the Event Admin service ensures that only handlers
that were registered at the time the event was posted will receive the event
notification.

Means that before posting an event, all handler are collected. This behavior isn't asynchronous but the notification is. To be more explicit, let's start an example.

In the entreprise OSGi applications, we have to register more EventHandlers ( > 100000) listing one queue. Sending an event to this queue using post will take a moment waiting to collect all handlers. This behavior will block the post event as if it is a synchronous delivery process.

Let's register 50000 EventHandlers to our POST_EVENT_QUEUE

 for (int i = 0; i < 50000; i++) {
context.registerService(EventHandler.class.getName(), new MultiPostEventHandler(), dp);
}
where MultiPostEventHandler do nothing ( no delay) else printing a message.
public class MultiPostEventHandler implements EventHandler {


@Override
public void handleEvent(Event event) {
String value = event.getProperty("property").toString();
System.out.println("---------------->Post value : " + value);

}
}
We remark that our console output sleep more than 10 s before processing.

Conclusion

If you want to be asynchronous way you need to use send or post method inside a thread when you have a big number of EventHandlers.
Note : source code is under svn  on kenai : http://kenai.com/projects/posteventvssendevent/sources
Published at DZone with permission of its author, Slim Ouertani.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)