Today I'll take a look at IBM's Project Zero ("Zero") in more
detail and compare what I find to NetKernel.
Zero is described as an event-based system that passes state
outside of the event message. This means that event messages do not
have parameters and event handlers request all state for each
invocation. Zero uses a concept called a zone to contain
state. The documentation lists the App, Request,
User, and Event zones. The App zone contains
information valid for the life of the application. The Request zone
is visible to the thread processing an HTTP request and is valid up
until the response is sent back to the client. The User zone is
visible to all threads processing requests for a specific user's
session. The Event zone is visible only to the thread dispatched to
an event handler and is valid until the event handler returns.
In Zero, code can access state within these zones using a URI
based hierarchical naming system. In Java code the GlobalContext is
used to get and put information. For example:
GlobalContext.get("/request/uri")
will retrieve the original HTTP request URI and
GlobalContext.put("/request/status",200)
sets the return status. In Zero, the first part of the path is a
key into each of the zones - these examples are using the
request zone. New zones can be created by writing a
ZoneHandler. The second part of the path is the sub-context which
provides a limited set of operations such as dump() and a keys()
operation.
Zero provides a mechanism that parses HTTP request and provides
the information in a normalized URI address space within the
request zone. Here are some example URIs that are
supported:
/request/protocol
/request/scheme
/request/serverPort
/request/params
A full listing is available in the Zero documentation.
Events in Zero are handled by event handlers. Event
handlers are registered in the configuration information and are
associated with events that can occur in the system. For example, a
request for the (partial) URL /foo/Hello.groovy could be registered
as:
[/app/handlers/GET[]]
handler=acme.handler.GetHandler.class
conditions=[/request/path matches /foo(/.*)?]
Handlers then implement a set of standard method signatures such
as onGet(), onPOST(), onPUT(), onDELETE(), etc. Zero supports a
standard set of events and developers can add new ones. Events are
fired using static methods on the EventEngine:
public class EventEngine {
public static EventContext fire(String eventName, Map eventData) {...}
public static EventContext fire(String eventName, Map eventData, EventDispatcher dispatcher) {...}
There is much more to Zero, but I will wait and explore more
later. Next I want to compare this much of Zero with NetKernel.
Comparison with NetKernel
The opening description for Zero in its documentation
establishes a key difference between Zero and NetKernel. Zero is an
event-based system and NetKernel is a resource-oriented computing
system. Yes, there is a concept of resources in Zero, but they play
a supporting role whereas in NetKernel it is the central
concept.
Resources
Resources in Zero are defined within the context of a virtual
directory system. Each resource uses a virtual directory and is
mapped into the /rest/... sub-space of the global context. For
example, if people is a resource, then /rest/people is the
location of the resource and the collection.groovy and item.groovy
scripts within the virtual directory handle the aggregate and
individual "items". The collection script is responsible for list
and member creation while the item script is responsible for
retrieve, update, and delete operations. This approach to resources
has a distinct CRUD (Create, Retrieve, Update, Delete) feel
to it, similar to Ruby on Rails and other result-set centric
database-grounded frameworks.
Resources in NetKernel are very different. They are abstract,
typeless and take on any form required by a system. Resources in
NetKernel are fundamental and pervasive; they can be transformed by
services and composed into more complex resources. For example, the
result of using the sqlQuery service in NetKernel is a resource
that can be transformed using the xslt service into HTML. Resources
in NetKernel can flow through a chain of services (just like
chaining the Unix toolkit- cat, grep, awk, etc.) to create the
desired final information representation. Applications written in
NetKernel focus on the necessary information model (and the
supporting URI address structures), the services required, plumbing
and routing and finally the application of constraints.
While Zero provides surface level support for resources it does
not seem to be a deeply implemented concept. For example, I have
not yet found how one would build services which take resources as
parameters and provide resources as the result such as can be done
in NetKernel with this URI:
active:xslt+operator@ffcpl:/style.xsl+operand@ffcpl:/data.xml
It is not clear if Zero could support a system-wide resource
cache like NetKernel's.
Address Spaces and Context
Zero stipulates that event-handlers are stateless and all state
exists globally with zones. Each zone has a different
operational context (such as being related to the application
lifetime or the user's session) and new zones can be created by the
developer.
In NetKernel the location of state in system is up to the
architect. Stateless or stateful services can be created to suit
system requirements. However, stateless services is the preferred
design approach and state can then be passed in parameters or
through environmental contexts.
While Zero has a single global context, NetKernel uses a general
idea of address spaces. NetKernel can support an unlimited number
of address spaces and within and between each address space,
mappings can be defined to perform address transformations. The
ability to create multiple address spaces and to establish
relationships between them is a very powerful capability that leads
to high-level architectural patterns. For example, it is very easy
in NetKernel to wrap an address space with a security gatekeeper or
a session manager - adding new application capabilities in an AOP
like manner.
Events
Events and event handlers are core elements of Zero's structure.
NetKernel is a request-response system in which a request for a
resource results in a resource-representation in the response. At
first glance it may seem the two are similar. However, NetKernel
implements a computational model while Zero does not. In NetKernel
the resource request is the operation code (op-code) of
the model. This has important implications.
One implication is the use of an engine - implemented as an
operating-system caliber micro-kernel - to execute the URI
op-codes. An execution engine provides a clear boundary between the
logical computation model using resources and the physical
implementation details. By hiding the details not only is the model
pristine, the implementation details can be changed without
impacting existing programs. This is not the case in an event /
event handler design in which programs are written to a physical
level API. Any subsequent changes to the implementation API will
necessitate coding changes in applications.
A second implication derives from the textual form of the
op-codes. In NetKernel the op-codes are literally a sequence of
ASCII characters. For example the op-code "ffcpl:/index.html" is
presented as the string of characters: 'f' 'f' 'c' 'p' 'l' ':' '/'
'i' 'n' 'd' 'e' 'x' '.' 'h' 't' 'm' 'l' to the engine. Because the
op-codes are strings, they can be manipulated within the logical
model. The execution engine supports pattern matching against
op-codes and substitutions via re-write mapping rules. For example,
a mapping rule can change all op-codes of the form:
ffcpl:/stock/price/closing/(.*)/(.*)
to
active:fetchClosingPrice+date@$1+symbol@$2
which would transform the op-code
"ffcpl:/stock/price/closing/2007-06-15/IBM" to
"active:fetchClosingPrice+date@2007-06-15+symbol@IBM". Another
mapping from
(active:.*)
to
active:gk+function@$1
routes all service requests through a security gatekeeper
service. This is model-level aspect-oriented programming, layering,
and more all within an execution model that can be dynamically
modified at run time.
This extraordinary flexibility and control - a dream of
object-oriented developers - is possible within a simple,
consistent execution model. Unfortunately, Zero only provides
resources at the surface level and is hence constrained in what it
can offer.
Conclusions
There is more to examine before reaching any final conclusions
about Zero, and I may have missed some points about the design in
this analysis. However, it is clear that the fundamental premise
for Zero and NetKernel are very different. Zero is an event-based
system with a simple and clean configuration and points of
extensibility. NetKernel is a logical computing model that uses
resources to model information. All development in NetKernel is
focused on building, using, and constraining compositions of
resources to provide the information requested by the user.
Ultimately, all computer systems no matter how designed and
built, must provide requisite services and information. When view
that way, NetKernel and the resource-oriented computing model seems
fresh, direct, and empowering. Zero seems grounded in a procedural,
physical-world way of thinking.