Cancelling events
Event listeners can not only act on events, they can even modify them. One of the most important feature is, that event listeners can cancel (i.e. abbort) the event.
If you ever used JavaScript to validate an HTML form, you've probably used somthing along these lines:
<form action="..." onSubmit="if (!formValid()) {return false;}">
...
</form>
By returning false in the =onSubmit= handler, the event will be cancelled and the form not submitted to the server. And with EventDispatcher, you can do something similar.
The following piece of code is an example of how easy it can be to implement a blacklist-check for the previously shown login mechanism.
public class BlacklistCheck implements EventListener { public void handleEvent(Event e) { String username = e.getContext().getUsername(); // user schst should be blocked if (username.equals("schst")) { // cancel the event e.cancel(); } } }
This blacklist check compares the username to the users that are blocked, and if a blocked user tries to login, it cancels the event. Now all you need to to, is add this event listener to the dispatcher.
EventListener log = new AuthLogger(); EventListener check = new BlacklistCheck(); EventDispatcher disp = EventDispatcher.getInstance(); disp.addEventListener("onLogin", check); disp.addEventListener("onLogin", log); disp.addEventListener("onLoginFailure", log);
If the user now logs into the site and the username is "schst", the BlacklistCheck listener will cancel the event. If the event is cancelled, it will not be propagated to all following event listeners and thus, there will be no log written for this user.
"Wait!", you might say, the user still is logged in to the application, and yes, you are right. Your application does not care, if any event listener cancelled or modified the event. To achieve this, some slight modifications are needed:
import net.schst.EventDispatcher.*; EventDispatcher disp = EventDispatcher.getInstance(); Auth user = new Auth(); if (user.authenticate(username, password) == true) { // User successfully logged in // We need to capture the triggered event Event e = disp.triggerEvent("onLogin", user); // any event listener has cancelled the event // login is not allowed if (e.isCancelled()) { user.clearAuthentication(); disp.triggerEvent("onLoginFailure", user); } } else { // login failed disp.triggerEvent("onLoginFailure", user); }
So all you had to do is add three lines of code and your application is even more flexible, as you can add any checks wihtout modifying the business logic. Now you can ban users based on any criteria or even ban all users if you need to do some maintanance work by just adding a new event handler.
