I'm attempting to decouple some UI code using interfaces and events, and I would like to know if there is way/best practice in Java for declaring an event as part of a Java interface - something like what C# provides:
// C# event declaration in interface
public interface IAction
{
event EventHandler OnAction;
}
My goal is simply to mark an interface so that it is known it (implementors) fires events of a particular type. I'm hoping I can include more than documentation only to enforce that behaviour. I realize Java does not provide the "event" keyword or a direct way of doing this, so I'm hoping for some advice on a workaround or best practice on achieving this.
One way I can think of doing this is by creating a generic marker interface that represents the capability to fire events:
public interface FiresEvent<T extends Event> {
public void fireEvent();
}
... and then to inherit that interface in my custom interface.
public interface MyInterface extends FiresEvent<ActionEvent> {
}
The problem with this approach is that "FiresEvent" can only be inherited once, even if the generic type changes, so the solution does not seem generic enough for the case where an object may be the source of multiple events.
I'd be curious to know how people would handle this, and if there is a better way than to just document the need to fire events.
EDIT:
Maybe the following will clear up my question:
I understand the Java handler list approach and self-handling by allowing callers to register handlers against an object. In my case I am relying on an event bus, so we can view "firing" events as putting them out there, for something else to redirect to handlers.
I'd like to define the interface responsibility as:
The interface implementer fires an event of type T into the world/event bus/anything
The interface implementer does not have to delegate to registered listeners itself
Java handles events a bit differently than what you're used to, however the concept is the same. You create what's called an event listener, and it's called when the event happens. This can be a better construct as it allows for multiple listeners to be registered.
I suggest browsing this tutorial
The presence of a method
registerXListener(XListener listener)
in the interface indicates that a class will send out XEvents to those that care. That is, the 'marker' is just another method. The nearest analog of the C# idiom (I think) would be to lift that method into an interface, like
public interface XEventFirer
{
public void registerXListener(XListener listener)
}
This seems like a natural place to use annotations. I have come across EventBus which uses annotations to for publishing and subscribing to events. This approach is naturally self-documenting and depending on how it's implemented could make your code more readable and maybe allow you to enforce the annotation.
Related
I appreciate this may not be a right/wrong type question, possibly more a stylistic thing but I often find myself pondering the use (overuse?) of custom Event and EventListener classes.
Frequently I have a class (often a GUI component) that needs to make other components aware of some change in it's state.
I could maintain a list of ChangeListeners (or some other already defined, general purpose listener type) and then call them on a state change, for example:
for (final ChangeListener cl : changeListeners)
cl.stateChanged(new ChangeEvent(this));
then retrieve the value in the listener:
class SomeListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
((MyClass) e.getSource()).getSomeStateProperty();
.
.
.
}
However the cast to MyClass strikes me as bad practice as the listener class is now making an explicit assumption about the contents of that ChangeEvent which has not been explicitly declared as the ChangeEvent constructor takes type Object.
So I frequently find myself creating pairs of custom Event and EventListener classes/interfaces i.e.
public interface SomeThingChangeListener extends EventListener {
/**
* Invoked when the target of the listener has changed some thing.
*
* #param e a SomeThingChangeEvent object
*/
void someThingChanged (SomeThingChangeEvent e);
}
With a corresponding Event class that contains a reference to the pertinent change information (probably a reference to an interface or abstract class in the event constructor).
The thing that bothers me about this however is the large proliferation of these small connector classes/interfaces for all 'things' that might 'happen' that may only ever have one concrete implementation.
So I guess the question is; is it best just to use general purpose events/listeners wherever you can or to always make class/event specific events and listeners?
The main reason that I seem to create quite a lot of these is that it often occurs to me that the association between two (or more) classes tends to be fairly weak, they are often not really related to each other in any way but one may be interested in information/state created/modified by another but not care about the details of the source. I find the observer or event/listener pattern a good way to keep coupling between unrelated classes to a minimum.
Any thoughts?
Thanks in advance,
Simon.
In my opinion defining specific types for each event, which makes up your domain model, is a good practice (one I do prefer / follow most of the times). Having as many event listeners as different event types may cause class pollution. On the other side, a generic listener approach leads to either determine the event type by sequences of instanceof or using the Visitor Pattern to dispatch events. The Visitor Pattern couples events to the listener. Perhaps a compromise between listeners capable of consuming more than one event (having change listener methods for related events) will reduce the number of different listeners by preserving event specific consuming, avoiding sequences of instanceof.
A proper solution depends on the concrete project and is always a tradeoff of many aspects.
While consulting the javadocs for GwtEvent class this text snippet got me confused:
There is no need for an application's custom event types to extend
GwtEvent. Prefer Event instead.
Can someone please give a concrete situation example where Event is preferred to the gwtevent class?
Should ClearEvent ( defined here : http://alextretyakov.blogspot.ro/2011/11/gwt-event-bus-basics.html ) extend GwtEvent class or should it directly extend Event class?
GwtEvent extends Event. It just seems that the GWT team need some functionalities for most of its events. But you probably don't need those.
In our application most events are consumed directly. So we don't need to have those isLive(), kill(), revive() methods. I guess it's the same for most people.
IMO such methods are required when a chain of listeners can catch the event and forward it to each other. You would want to mark the event as "processed" to avoid it being consumed when the processing is over.
The code in the post you provided is not using those methods. So the answer is: the author didn't need to extends GWTEvent. Event will work just fine.
I recently ran across several objects implemented to handle events with a hard coded mapping using this pattern:
public void handleEvent(Event event)
{
if(event.getCode() == SOME_STATIC_EVENT)
doSomething(event);
if(event.getCode() == ANOTHER_STATIC_EVENT)
doSomethingElse(event);
}
where doSomething functions are implemented as methods of the same class.
In hopes of striving for looser coupling, how would you suggest abstracting out this pattern? Also, what's the best approach for mapping 0..N functions to a fired event?
Yes, basically what you want to do is create a data structure that maps an event type to an interface. Here's a simple one implemented as a map.
EventHandlerInterface h;
// eventMap contains a mapping of event codes to
// implementations of EventHandlerInterface
h = eventMap.get(event.getCode());
if(h != null)
{
h.handle(event);
}
This gives you the ability to efficiently handle a large number of events and dynamically add, remove, and remap events to different handlers.
There was recently a SOF post that was similar and close enough that my response here can answer your question quite well.
Rather than a runnable, you would make your own interface:
public abstract interface EventHandler
{
public void run(Event event);
}
You can start by making the code a little cleaner. Use a local variable to take out the repeated event.getCode(). Switch to enums so you can use switch.
If there is a repeated pattern you can decode to a multiple method callback interface, like AWT does.
I would suggest that the registration of the even becomes more specific. Register a different callback for each event type. Even as far as taking the event code out of the event, and perhaps removing the event. Under the sheets you might keep the event code for a mapping to handlers, but this should be opaque. The downside to this approach is that anonymous inner classes are currently (JDK6) highly verbose and class handling is inefficient (load times and perm gen footprint).
I wrote a Listener. Now I want to notify it, when a change occurs. Nothing special.
Now I'm asking myself:
Is there I standard class for Events that I can use, or do I have to write a new one by myself?
I know there ara java.awt.Event and AWTEvent. But I am not working directly at GUI level here. Furthermore we are using Swing at GUI level. So I'm not shure if it is a good idea to mix Swing and AWT.
Thx
Its ancient and simple, but you could use Observer/Obserable in java.util:
java.util
public class Observable extends Object
This class represents an observable
object, or "data" in the model-view
paradigm. It can be subclassed to
represent an object that the
application wants to have observed.
An observable object can have one or
more observers. An observer may be any
object that implements interface
Observer. After an observable instance
changes, an application calling the
Observable's notifyObservers method
causes all of its observers to be
notified of the change by a call to
their update method.
For more info, try http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto.html.
There's nothing special about events in Java. If your events are not GUI events, then it would be less confusing for you to use your own class and not mix them with java.awt.Events.
If you are using swing, you can take a look at EventBus:
The Event Bus is a single-process publish/subscribe event routing library, with Swing extensions. The EventBus is fully-functional, with very good API documentation and test coverage (80+%). It has been deployed in many production environments, including financial, engineering and scientific applications.
I've always used EventObject as the base class for my custom events. Here's what the JavaDoc says:
The root class from which all event state objects shall be derived.
All Events are constructed with a
reference to the object, the "source",
that is logically deemed to be the
object upon which the Event in
question initially occurred upon.
Kind of a standard solution in Swing apps is to maintain a list of event listeners in the class the event originates from. When the event occurs you iterate over the list and notify each listener of the event. So it can be something like this (I omitted the access modifiers and some of the type declarations for brevity):
class SomeClassInWhichTheEventOccurs {
List<MyListener> listeners;
void addListener(listener) { listeners.add(listener); }
void removeListener(listener) { listeners.remove(listener); }
void fireEvent(someEventParameters) {
foreach (listener in listeners) listener.eventOccured();
}
void someMethodInWhichTheEventOccurs() {
...
fireEvent(someEventParameters);
}
}
The event parameters can be just anything: you can create your own event class, reuse java.awt.Event, or pass some parameters of arbitrary types.
Swing is based upon AWT, so you have to mix it. The problem comes with mixing AWT heavyweight components with Swing lightweight components. Don't use AWT heavyweight components.
Just to be notified that something has changed javax.swing.event.ChangeListener is fine. In fact, so long as you are not using a library that assumes the beans model, you can ignore event classes and use a observer without an event object.
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?
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.
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.
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?
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.
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.
In Java this would be a provider firing notifications to its listeners. But Java does not offer the loose coupling you get with Cocoa's NSNotification because in Java providers and subscribers must have references to each other. Compare for this chapter 18 in "Learn Objective-C for Java Developers".
There is an implementation of IOS NSNotificationCenter in Java.
You can find sources code in :
This Github project