views:

399

answers:

5

I am writing a Java application using SWT widgets. I would like to update the state of certain widgets upon a certain event happening (for example, updating the data model's state).

Is there something in Java similar to Cocoa's NSNotificationCenter, where I can register an object to listen for notification events and respond to them, as well as have other objects "fire off" a notification?

+1  A: 

What sort of notifications are you looking for? If all you want is for one object to be able to tell anybody else "hey, I've changed, update accordingly", the easiest way is to use the existing Observer interface and Observable class. Or write your own with an interface that defines what you want to get called on the listeners from the one that's changed.

Paul Tomblin
A problem with Observer/Observable is that I am already subclassing, and so I can't extend Observable.
Alex Reynolds
Like I said, it's dead easy to do it yourself. The main thing is to have an "addListener" method to adds the listener to a List, and then whenever you want to fire an event, go through all the listeners and call them.
Paul Tomblin
Would you know where I might find sample source code that describes this approach? I've been searching Google but my searches only find rudimentary Observer/Observable examples.
Alex Reynolds
That's because the Observer/Observable pattern IS rudimentary. It's really not that complicated. The complicated parts are mostly ensuring that objects are properly cleaned up, as they tend to linger in the Listener lists.
Will Hartung
+2  A: 

Ok, suppose that for example, you want parts of your program to be notified when your Loader starts a scan, and when it finishes a scan (don't worry about what a Loader is, or what a scan is, these are examples from some code I have lying around from my last job). You define an interface, call it "ScanListener", like

public interface ScanListener
{
  public void scanStarted();
  public void scanCompleted();
}

Now the Loader defines a method for your other code to register for callbacks, like

public void addScanListener(ScanListener listener)
{
  listeners.add(listener);
}

The Loader, when it starts a scan, executes the following code

for (ScanListener listener : listeners)
{
  listener.scanStarted();
}

and when it finishes, it does the same thing with listener.scanCompleted();

The code that needs to be notified of these events implements that interface (either themselves, or in an internal class), and calls "loader.addScanListener(this)". Its scanStarted() and scanCompleted() methods are called at the appropriate times. You can even do this with callbacks that take arguments and/or return results. It's all up to you.

Paul Tomblin
A: 

There's no pre-existing per-process service that dispatches events in java that's equivalent to the default NSNotificationCenter. In java, the type of the event is specified by the event object being a particular type (which also means that the notification method depends on that type) rather than using a string. Prior to generics, writing a general event dispatcher and receiver that is also typesafe isn't really possible (witness the proliferation of *Event classes and *EventListener interfaces in the AWT and Spring libraries).

There are some facilities for event dispatch. As Paul mentioned, there's java.util.Observable, which as you point out, requires subclassing. There's also java.beans.PropertyChangeSupport, which could be useful depending on your situation.

You could also write one yourself. The source for PropertyChangeSupport is likely available in the openjdk, and you could look at the abandoned Apache Commons Event project. Depending on your needs, you may have to worry about stuff like threading, seralization, memory leaks (ensuring deregistration or using weak references), and concurrent modification (iterate over a copy of your list of listeners, as a listener may decide to unregister itself in response to a change).

Now that generics exist in Java, a generic event dispatch library would be possible; however, I haven't come across any. Anyone?

Warren Blanchet
A: 

Not Java, but the IPython project has a notification center written in Python here that you could use as a template for a Java version.

Barry Wark
A: 

There's actually a facility built in to Java that does exactly what you want, but it's not something you may have considered, and, to be honest, it is likely a bit heavyweight for what you want.

That said, however, it does exist.

It's JMX.

You create MBeans, and then others can register for events from those MBeans. The MBean can then send of a Notification.

I personally wouldn't consider using it for this case (I'd just pound out my own), but the facility is there and it well defined and documented.

Will Hartung