Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

OSGi : PostEvent vs SendEvent in New Thread

DZone's Guide to

OSGi : PostEvent vs SendEvent in New Thread

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

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

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}