EventBus: How to Publish & Subscribe on the NetBeans Platform
The best solution is to have neither of the two depending on each other. You can achieve that with my favorite decoupling pattern, "publish and subscribe": define a set of messages ("topics"), define portions of code that register interest in those topics and receive an asynchronous notification ("subscribers") , and define portions of code that publish and unpublish those topics ("publishers"). Then you're done. All the components can now communicate without knowing about each other, while only depending on the messaging infrastructure and on the topics.
Indeed, this is one of the first parts that I developed in blueMarine when I ported it to the NetBeans Platform more than two years ago, and it was a pretty good improvement from the previous design. The implementation was focused on the NetBeans Platform's Lookup class, one of the most powerful in the NetBeans Platform. While it is mostly used for looking up services registered in the application, it is also used by the NetBeans Platform runtime to store relevant objects (such as selected items in a list) and to notify listeners (such context sensitive actions). So I basically used a global Lookup provided by the NetBeans Platform, "Utilities.actionsGlobalContext()", to listen for selections that were made in TopComponents. It seemed a pretty logical way to work, since TopComponents usually contain an ExplorerManager that automatically receives notification of selected Nodes in trees or lists that are placed inside the TopComponent. So, the flow of events is:
select a node in a tree -> notification published to ExplorerManager -> notification published to the actionsGlobalContext() -> notification received by my listener.
With this approach, you can use the class information as the 'topic': when you select a Node, everything that is inside its private Lookup (for instance, the DataObject) gets published. DataObject is obviously one of the most used topics by blueMarine (representing photos) and delivers information about selecting a single object: to notify that a set of DataObjects has been prepared, I defined a specific class named DataObjectSelection; to notify that there is a selection task running in the background, another specific object (DataObjectSelectionInProgress) is used, so viewers can display a "Please wait" message.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)






Comments
Aljoscha Rittner replied on Fri, 2008/10/17 - 8:22am
Excelent, I like the clean implementation. IMHO many RCP projects need this feature.
best regards, josh.
Pavan Kumar Sri... replied on Fri, 2008/10/17 - 12:45pm
We can also use the EventBus API from https://eventbus.dev.java.net/ , which could easily be used in existing swing apps which don't use the netbeans platform .
vincent cobra replied on Fri, 2008/10/17 - 6:21pm
Last time I tried to use EventBus from java.net, few months ago, it was buggy, so I had to roll my own implementation(not open source).
It would be more interesting and probably more useful to contribute to the existing EventBus project instead of writing such a library in my opinion. EventBus probably does a whole lot more already.
Jean-Francois P... replied on Fri, 2008/10/17 - 7:52pm
Why reinvent the wheel?
I have done that myself a couple of years ago (I think a few month before the "EventBus" project on java.net) and made it OSS (if you are interested, you can take a look here http://hivetranse.sourceforge.net/ but i's covered with dust now;-))
Java.net EventBus already does all that (and has been existing for several years now).
If EventBus has bugs, then anyone can report these and even contribute (it is OSS after all).
Pavan Kumar Sri... replied on Sat, 2008/10/18 - 3:13am
in response to:
Jean-Francois Poilpret
Yeah...very true....that should be our approach instead of re-inventing the wheel...
Fabrizio Giudici replied on Sat, 2008/10/18 - 3:29am
Tim Boudreau replied on Wed, 2008/10/22 - 8:45am
Slight preference for
to notify() as the method name. Generally on* makes a more readable pattern for listener-like things (and avoids confusion with Object.notify() and friends.
-Tim
Michael Bushe replied on Thu, 2008/11/06 - 7:52pm
in response to:
vincent cobra
I own the EventBus project. This is the first time I ever heard someone call the EventBus "buggy." I take bug reports very seriously. There are no open bugs in the project and there have only been 7 bug reports in its history, most minor and in beta versions. If you identify a bug, please add an issue to the java.net project, or if you don't won't to be bothered, send an email. If it's a real bug, I will likely fix it within 24 hours.
You probably ran into an issue with using WeakReferences by default. If you call subscribe (and don't call subscribeStrongly) and nothing else holds a reference to that object but the EventBus, then the object will be garbage collected. This is a feature, not a bug. A warning to new users appears on the website, the examples and the javadoc, it's probably mentioned about 20 times in total.
Michael Bushe replied on Thu, 2008/11/06 - 8:13pm
in response to:
Fabrizio Giudici
Fabrizio,
The EventBus' has some pretty cool options for locally-scoped convesations. One is the ContainerEventServiceRegsitrar and ContainerEventServiceFinder.
If a component needs to subscribe to an event in it's container, create a ContainerEventServiceRegsitrar on its construction:
<code>
public MyFormCombo extends JComboBox implements EventSubscriber {
public MyFormCombo() {
new ContainerEventServiceRegsitrar(this, this, MyEvent.class);
}
}
</code>
This is kind of magical in the sense that registrar will wait until the component is added to a container. When it is, then it searches up the containment hierarchy to find a locally scopped SwingEventService. If a parent implements ContainerEventServiceSupplier (perhaps implemented by MyFormPanel), then it uses it. Otherwise, it dynamically creates one on the JRootPane (so it covers dialogs, frames, internal frames, docing components, etc.) and subscribes the component to MyEvent.class. If the component is moved, it readjusts the subscription to the new container.
To publish to the container, use the ContainerEventServiceFinder:
<code>
ContainerEventServiceFinder.getEventService(someComponentInTheLocalScope).publish(new MyEvent("Hello!"));
</code>
I'm hoping I find the time to figure out the best ways to integrate this into Netbeans RCP, I like your suggestion, Fabrizio.
Michael
Michael Bushe replied on Thu, 2008/11/06 - 8:17pm
in response to:
Michael Bushe
The other option is the EventServiceLocator for publishing on private "channels" (or busses):
EventServiceLocator.getEventService("MyPrivateChannel").publish("Foo", new Bar());//topic example
Ashley Ford replied on Tue, 2011/01/11 - 1:24pm
I wish I had known about publish and subscribe sooner! I followed your suggestion to set parameters for search and I am really happy with the results.
Everyone is buzzing about 'local search'. I run my own business ("Family Leisure") and I want to try and reach out to customers using more than just Google and Facebook. Is there a platform I can utilize to make this easier? Thanks!
Tina Figgler, Family Leisure
Ashley Ford replied on Tue, 2011/01/11 - 1:22pm
in response to:
Michael Bushe
Carla Brian replied on Mon, 2012/04/16 - 6:50pm
Martin Sooner replied on Sun, 2012/04/22 - 6:42am
Gilber Mantis replied on Fri, 2012/04/27 - 3:48am
in response to:
Pavan Kumar Srinivasan
Mateo Gomez replied on Mon, 2012/05/21 - 3:42am
in response to:
Aljoscha Rittner
very clean implementation indeed
mexican dip recipes
Matt Coleman replied on Thu, 2013/03/14 - 12:53am
in response to:
Aljoscha Rittner
very clean indeed...i agree on all points
buffalo search engine optimization