Working with server event listeners

WARNING : This howto is a work in progress!

Summary

This tutorials will guide you through the use of server event listeners.

Server event listeners were introduced in Harfang 0.3 in order to facilitate error handling inside applications. In Harfang 0.1 and 0.2, error handling was centralized inside the ServerConfiguration interface. Although it was simple in the sense that error handling was centralized at one place, delegating error handling to an application's sub components like modules was cumbersome.

Hence, server event listeners were introduced.

The tutorial

The ServerEventListener interface

Harfang 0.3 introduces a new interface, harfang.server.event.ServerEventListener. This interface defines various methods to handle events ranging from errors to notifications.

Regarding errors, ServerEventListeners offer two methods : onHTTPError and onError. These methods are called when errors happen within the application (either when the framework encounters an error or when the developer explicitly throws an Exception). The difference between HTTP errors and "plain" errors is slim. HTTP errors are thrown when it can be matched to an HTTP error code. For example, a user landing on an unknown part of the site throws a 404. A user trying to access a part of the application that he doens't have any access for might throw a 401. Although most internal errors might all be contained in 500 errors, "plain" errors are used when they cannot be mapped to an HTTP status or when the developer just want to handle some exceptions differently. For example, you might want to catch an exception without necessarily relaying the information to the user in the form of a status code.

Regarding notifications, the onDispatch and onDispatchInterrupted provides a way of knowing, outside of controllers, what has been called by the URL dispatcher and when a request has been interrupted.

onDispatch is called when the URL dispatcher finds a match between a controller and an URL and that the controller lets the URL dispatcher call the mapped method. In short, onDispatch is called only if the URL dispatcher finds a match and that the Controller's handleRequest returns true.

On the other side, onDispatchInterrupted is called when the URL dispatcher finds a match but the Controller's handleRequest returns false, indicating that the URL dispatcher found a controller and method to call, but was not allowed to call it.

Listening to events

In order to be able to listen to events, you must implement the harfang.server.event.ServerEventListener interface and add your listener to the server's configuration. The ServerConfiguration interface defines a "getServerEventListeners" method that must return all of the server event listeners that must be taken into account.

AbstractServerConfiguration, the parent class of UserConfiguration, offers a method called "addServerEventListener" that you can call to easily add your event listeners to your configuration. By default, AbstractServerConfiguration implements ServerEventListener and adds itself to the list of active listeners at initialisation. Therefore, if you just upgraded from Harfang 0.2 or Harfang 0.1, you may already listen to events since the methods that were used back then to catch errors were kept in order to keep backwards compatibility. Only now, you may choose to put the error handling logic out of the configuration.

Creating a simple listener

First of all, create this class (don't forget to specify your destination package):

import harfang.exception.Exception;
import harfang.exception.HTTPException;
import harfang.server.event.ServerEventListener;
import harfang.url.URLMapping;

#if php
import php.Lib;
#elseif neko
import neko.Lib;
#else
#error "Unsupported platform"
#end

/**
 * A simple listener
 */
class SimpleEventListener implements ServerEventListener {

    public function new() {}

    /**
     * This will print the contents of an HTTP error to the client when
     * an exception is caught.
     *
     * @param exception The exception that was thrown
     */
    public function onHTTPError(exception : HTTPException) : Void {
        Lib.println(exception.getErrorCode() + " error");
        Lib.println("Cause : " + exception.getMessage());
    }

    public function onDispatch(urlMapping : URLMapping) : Void {}

    public function onDispatchInterrupted(urlMapping : URLMapping) : Void {}

    public function onError(exception : Exception) : Void {}
}

This class will print the error code and its message back to the user whenever an HTTP error happens. All that is left is to add it your listeners.

Iniside UserConfiguration's init method, add your listener this way :

class UserConfiguration extends AbstractServerConfiguration {
    [...]

    public override function init() : Void {
        [...]

        // Add your listener here!
        this.addServerEventListener(new SimpleEventListener());

        [...]
    }

   [...]

Now, anytime an HTTP error is thrown in your application, it will be printed out. For example, if you try to access a page that doesn't exist, it should show this in the browser :

404 error Cause : Page not found!

Or, in source view :

404 error
Cause : Page not found!

version #15591, modified 2012-10-26 02:54:31 by njuneau