GC Enhancements for M3

GC enhancements for M3 are being coordinated under bug 1881. The changes are in trunk.

Objectives

  • Provide a common GC API across programming languages (Java, Groovy, PHP). We're close already. By renaming methods in a few places, we'll be the same.
  • Clarify the use of the GCAccessor, which is the Groovy shortcut for GC access. Use of the GCAccessor is optional.
  • Improve usability of the GC APIs. For example:
    • Simpler get(): GlobalContext.zget(uri) will return null if the uri is not found (rather than throwing an IllegalArgumentException).
    • Simpler "walking": GlobalContext.zlist(uri) will return a list of child URIs. Thus, zlist() will be useful for "walking" through the GC.

Summary of changes

Revised GC APIs

The GC APIs now have a "z" prefix as a simple means of reducing namespace collisions.

The following sections describe the new syntax and behavior changes in the GC API. We'll use examples based on the following GC contents:

/config/foo/a = b
/config/foo/x = y
/config/map = ["a" : "b", "x" : "y"]

Syntax Comments/examples
T zget(String uri [, T defaultValue]) zget("/config/foo/a") == "b"
zget("/config/foo") == null (M2: threw an exception)
List zlist(String uriPrefix [, boolean includePrefix]) Returns a list of children of uriPrefix
(M2: returned all uris that started with uriPrefix).

zlist("/") == ["/config"]
zlist("/config/foo") == ["/config/foo/a", "/config/foo/b"]
zlist("/config", false) == ["foo", "map"]
boolean zcontains(String uri) Was containsKey(uri) in M2
Handles value path (M2:  no value path)
=zcontains("/config") == true

zcontains("/config/map#a") == true
T zpost(String uri, V value) Same as M2.
T zput(String uri, V value) Same as M2.
Map zputs(String uriPrefix, Map payload) Was available in Groovy for M2.
map.put("w", "z")
zputs("/config/bar", map)
zget("/config/bar/w") == "z"
void zdelete(String uri [, boolean deleteChildren]) Same as M2.
String zdump(String uri) Same as M2.

Java: Using static imports

Java code can be a clean demonstration of the GC APIs by using static imports, as follows:

Java example

import static zero.core.context.GlobalContext.*;
public class MyHandler {
  public void onGET() {
    String qvalue = zget("/request/params/qname");
  }
}

Groovy: Added method bindings for GC APIs

All .groovy scripts, as well as classes that implement ZeroObject , receive bindings for the GC APIs. So, there's no need to import GlobalContext.

Revised exception conditions

In M2, GlobalContext.get(uri) threw an IllegalArgumentException if uri was not found. Most of the other APIs were more friendly, returning default/empty values, even if uri was ill-formed.

In M3, zget(uri) returns null if uri is not found. This is equivalent to zget(uri, null).

Another significant change in M3 is that all of the GC APIs throw an IllegalArgumentException if the uri is ill-formed. A valid GC uri has the following characterics:

Description Valid example Invalid example (throws IllegalArgumentException)
Starts with a slash zget("/") zget("config")
Path does not end with a slash zget("/") is valid zget("/config/")
zget("/config/#any")
Not null zget("/config") zget(null)
Not empty zget("/") zget("")

Groovy: Clarified GCAccessor

GCAccessor is the support behind the GPath-like interactions with the GC. An example from M2:
def id = request.params.userId.get()
request.status = 202

This approach was rather confusing because we tried to use the GCAccessor to represent data, but it didn't always work that way (note the occasional need for .get()). Also, there were other use cases where we wanted to extract the GC URI or an accessor object from the data (ref. [[http://www.projectzero.org/wiki/bin/view/Community/JasonsBlog/BlogEntry5][.toPath() and .toGPath()]), which stretched the intuition.

For M3, GCAccessor has been reworked to be just that: An accessor object. It's been integrated into the Groovy syntax, as summarized here:

GC API Groovy shortcut
zget(uri) Always ends with brackets; empty brackets are valid.
def m = request.method[]
def id = request.params.userId[2]
zget(uri, defaultValue) def id = request.params.userId.zget('anonymous')
zlist(uriPrefix) request.headers.in.zlist()
request.headers.in.zlist(true)
zcontains(uri) request.headers.in.zcontains('X-METHOD-OVERRIDE')
zpost(uri) request.headers.out.MyHeader << ['MyValue']
zput(uri) request.method = 204
zputs(uri, payload) request.headers.out.zputs([MyHeader : 'MyValue'])
zdelete(uri) user.counter.zdelete()
zdump(uri) request.zdump()

The following property bindings are GCAccessor objects available by default to all .groovy scripts and class implementations of ZeroObject:

  • app
  • config
  • event
  • headers
  • request
  • user

Additional bindings may be registered using the same method as for M2.

A more complete set of examples are available in the zero.core.tests unit test cases.

Groovy: Removed _gc binding

Use method bindings (e.g. zget('/request/method')) or GCAccessor bindings (e.g. request.method[]) instead.

Zone handlers

Changes for ZoneHandler implementations:
  • No longer implement containsKey(); this is now handled in the GlobalContext implementation.
  • Must implement isAvailable(). Currently used to control access; may be removed early next week. Depends on whether the zone handlers can be self-protecting on the normal ZoneHandler APIs without inadvertent auto-activation.

Changes for ThreadLocalZoneHandler implementations:

  • That interface has been removed; replaced with ActivatableZoneHandler interface.

Porting notes

  • Search .groovy and .gt files for instances of .get(); replace with [] for GC accessors.
  • Search .groovy and .gt files for .condGet(uri, null); replace with [].

While debugging, if you find that a variable comes through with what looks like a path instead of a value (e.g. /request/status instead of 200), then you're probably missing a [] on the property binding. That is, you probably have def x = request.status where you should have def x = request.status[].

r4 - 09 Nov 2007 - 09:48:53 - steveims
Syndicate this site RSS ATOM
Copyright 2007 © IBM Corporation | Privacy | Terms of Use | About this site