Event processing
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
resolveHandlershandlers, that are themselves explicitly registered. - Event handlers are invoked using registered
Interpreters. By default,Interpretersare 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
log and requestEnd handlers run, regardless of exceptions encountered during the previous events.
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");
}
}
/event/result then that value is be returned when the /event/uri is requested. Therefore, zget("/request/foo") returns "some value".