The Delegation Event Model is used in Java to handle events. AWT and Swing API provides many event listener and adapter classes to handle various type of events on GUI components. In this blog post, I’m writing about creating and handling non-UI and custom events in Java.
Non-UI and custom events are common in applications. We usually write the event handling code for such events in methods and mock the occurrence of an event as a method call. If the event handling code varies then we employ overloading or overriding or loose-coupling by providing many class implementations for an interface. When we want even more flexibility of enabling or disabling the execution of event handler method then we often use a boolean flag within the method to decide whether the business logic in it should be executed. Writing code to enable/disable execution within method by using multiple boolean flags when you need to enable/disable multiple events on a common source can be quite complex.
It is easy to mimic event occurrence as method calls. However, when you want the flexibility of enabling or disabling the event handling then it is easier to code the event as custom event. All events in Java are subclasses of EventObject
. The custom event class should also extend this class.
An example of a custom event is the request for approval when a new workflow request is created. For writing custom event handling code these classes are required – event class, event listener, event source class, class implementing event listener or adapter class.
The event class is given in Listing 1. The event listener is given in Listing 2. The event source class is given in Listing 3. The event listener implementation class is given in Listing 4. Code to fire event is given in Listing 5 and code to instantiate and assign event listener implementation class and register the event listener is given in Listing 6.
public class ApproveRequestEvent extends EventObject { public ApproveRequestEvent(WorkflowRequest request) { super(request); } }
Listing 1. Event class
public interface WorkflowRequestStateChangeListener { public void handleEvent(ApproveRequestEvent event); ... }
Listing 2. Event Listener
public class WorkflowRequest { private List<WorkflowRequestStateChangeListener> listeners = new ArrayList<WorkflowRequestStateChangeListener>(); synchronized void addListener(WorkflowRequestStateChangeListener listener) { listeners.add(listener); } synchronized void removeListener(WorkflowRequestStateChangeListener listener) { listeners.remove(listener); } }
Listing 3. Event source class
public class WorkflowRequestStateChangeListenerStandardImpl implements WorkflowRequestStateChangeListener { public void handleEvent(ApproveRequestEvent event) { WorkflowRequest request = (WorkflowRequest)event.getSource(); ... } }
Listing 4. Event listener implementation class
public class WorkflowFacade { private WorkflowRequestStateChangeListener listener; public WorkflowFacade(WorkflowRequestStateChangeListener listener) { this.listener = listener; } public void save(WorkflowRequest request) { //save workflow request in database ... //fire event to request approval listener.handleEvent(new ApproveRequestEvent(request)); } }
Listing 5. Code that fires event
WorkflowFacade facade = new WorkflowFacade(new WorkflowStateChangeListenerStandardImpl()); WorkflowRequest request = new WorkflowRequest(); //register listener to the source request.addListener(listener); facade.save(request);
Listing 6. Code to assign event listener implementation instance and register event listener to event source
Using custom events than simply calling methods has an advantage. The code to add and remove event listener on the event source is simple. The event listener can be added or removed in the code outside the event handling code. The event listener implementation or in other words the event handling code can be changed on the fly. An off-the-shelf component can also be used to define the event handler logic if it implements appropriate event listener interface.
Writing such a code with custom events appears more logical than calling methods. However, custom events can increase the code complexity. Hence it is recommended to use them only when they are needed.