Event processing

IBM® WebSphere® sMash applications can define, fire and handle events to interact with the various handlers within the WebSphere sMash platform.

Overview

Events in the WebSphere sMash platform orchestrate behavior in the form of loosely-coupled event handlers. WebSphere sMash fires a fixed set of events for HTTP request processing and stages of the application life cycle; developers can add other event types.

Firing an event equates to an API invocation (see the Firing events section for details). This causes WebSphere sMash to invoke the associated handlers through an EventDispatcher. The set of associated handlers is determined by the following mechanisms:

Explicit registration
Evaluates registration rules. See the Event Handler Registration section for details.
Implicit registration
Identifies scripts as handlers through convention.

For example, consider a request for GET /foo/Hello.groovy. An explicitly registered handler might have an entry in a configuration file as shown in the following example:

/config/handlers += [{
   "events" : "GET",
   "handler" : "acme.handler.GetHandler.class",
   "conditions" : "/request/path =~ /foo(/.*)?"
}]

For more information about the configuration file, see the Configuration section.

By convention, the file foo/Hello.groovy in the public virtualized directory is also associated with the request. For more information, see the Virtualized directories section.

Handlers generally implement methods named to match the corresponding event (for example, onGET() handles the GET event). Handlers can be implemented in various languages, including Java™, Groovy, and PHP. For more information, see the Writing Java handlers and Writing Groovy handlers sections.

Event dispatchers govern the behavior of the core event processing engine, including early termination criteria and error handling. For example, the Dispatcher for the GET event allows no more than one handler to be invoked.

  • Implicit registration is performed by resolveHandlers handlers, that are themselves explicitly registered.
  • Event handlers are invoked using registered Interpreters. By default, Interpreters are registered for Java classes (.class), Groovy scripts (.groovy), and Groovy templates (.gt).

Request-processing events

The following table summarizes the events, in order, fired by WebSphere sMash during HTTP request processing:

Event name Description Maximum number of handlers invoked Early termination criteria Reaction to Exceptions
requestBegin   No limit /request/status is set Return status code 500; skip to the log event
secure Perform authentication and authorization checks 1 /request/status is set Return status code 500; skip to the log event
GET, PUT, POST, DELETE Generate response 1 /request/status is set Return status code as noted below; skip to the log event
log   No limit N/A Ignored
requestEnd   No limit N/A Ignored

Error status codes returned for exceptions on the GET, PUT, POST, and DELETE events depend on the exception type:

FileNotFoundException
reported as status code 404
NoSuchMethodException
reported as status code 405
RuntimeException
catch-all for all other exceptions; reported as status code 500
All log and requestEnd handlers run, regardless of exceptions encountered during the previous events.
Handler exceptions are caught and categorized by the associated Interpreter.

 

resolveHandlers event

The resolveHandlers event enables dynamic registration of handlers. This special event can be fired as part of the process of identifying handlers for events. File-serving functionality in WebSphere sMash includes serving static files and running scripts. Static-file serving is handled by the zero.core.fileserver.FileServer handler; running scripts is handled by the corresponding Interpreter. For example, zero.core.interpreter.GroovyInterpreter runs for .groovy files.

Rather than register all combinations of file types, locations and handlers in a configuration file, one resolveHandlers handler (zero.core.fileserver.FileServerResolver) provides the appropriate handler based on the request.

The following special values are placed into the global context for resolveHandlers:

/event/resolvingEvent
Contains the name of the underlying event.
/event/resolvedHandlers
Contains a List<handlerData> of handlers associated with the event.

resolveHandlers handlers are generally registered as resolvers for specific events using /event/resolvingEvent, as shown in the following example:

/config/handlers += [{
   "events" : "resolveHandlers",
   "handler" : "zero.core.fileserver.FileServerResolver.class",
   "conditions" : "/event/resolvingEvent =~ (GET|POST|DELETE|PUT)"
}]

For example, the FileServerResolver manipulates the list of associated handlers as shown in the following example:

public void onResolveHandlers() {
        
        // path is path from the request
        String path = zget(Request.path);
        HandlerData handlerData = getResolveHandler("public", path, true);
        // ...
        zpost("/event/resolvedHandlers", handlerData);
}

public static HandlerData getResolveHandler(String appSubdir, String path, boolean serveDirectories) {
        // First match wins; search order: app, then dependencies in ivy.xml
        List<String> listOfDependencies = zget("/config/dependencies");
        for (int i = 0; i < listOfDependencies.size(); i++) {
                String dependency = listOfDependencies.get(i);
                String dependencyRoot = zget("/config/dependencies/" + dependency);
                
                HandlerInfo info = getResolveHandler(dependencyRoot, appSubdir,
                path, serveDirectories);
                
                if (info != null) {
                        HandlerData handlerData = new HandlerData(info, null);
                        return handlerData;
                }
        }
        return null;
}

gcMiss event

The gcMiss event defers an operation until a specific global context URI is requested. This event can be used for a single initialization or lazy loading of various components of an application. The following example shows the gcMiss configuration syntax:

/config/handlers += [{
  "events" : "gcMiss",
  "handler" : "aaa.bbb.SomeHandler.class",
  "conditions" : "/event/uri == /request/foo"
}]

The handler implementation is shown in the following example.

public class SomeHandler {

    public void onGcMiss() {
        GlobalContext.zput(GlobalContextURIs.Event._self + "/result", "some value");
    }
}
The handler sets a value at /event/result then that value is be returned when the /event/uri is requested. Therefore, zget("/request/foo") returns "some value".

Version 1.1.0.0.21442