e-Zest members share technology ideas to foster digital transformation.

Custom Events In Java

Written by Madhura Oak | Oct 22, 2012 2:50:08 PM

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.