Steve Bjorg

Subscribe to Steve Bjorg: eMailAlertsEmail Alerts
Get Steve Bjorg: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: SOA & WOA Magazine

SOA & WOA: Article

WOA for the Enterprise

An alternative architectural style

WOA by Example
Let's apply WOA to build an image analysis application. Since WOA is based on RESTful principles, we need to define our processing application in terms of locations, actions, and representations.

Images to be processed will be submitted to our analyzer. We'll use Atom as our representation for work items. Atom was conceived as a syndication format, but has gained traction as a common representation in WOA. Notably, Google uses it for its GData API. Atom defines two types of XML document types: the Atom entry, representing a single item, and the Atom feed, representing a collection of items. We'll use both for our application.

Our application needs to handle the following activities:

  • Submitting a work item to the analyzer
  • Updating of the metadata associated with the work item
  • Inspecting the queue of pending work items
  • Receiving a notification upon completion of the work item
  • Submitting a Work Item

We begin by submitting a new image of analysis to our analyzer. To do so, we upload the image to a storage service (e.g., Amazon's Simple Storage Service). We then build an Atom entry with the location of our image, a human-readable title, and an email address to be notified when the analyzer has finished processing the image. The document is submitted to the analyzer using the HTTP POST method. We can think of the analyzer as a queue of pending images to be analyzed. The POST method tells the analyzer that we wish to submit a new item.

Listing 1 shows the raw HTTP request. WOA specifications are commonly described in this is technology-agnostic form. With a bit of experience, a reader can adapt it to any programming language or tool chain, as well as gain an understanding of what information is actually exchanged between the agent and the resource.

Building XML documents with namespaces and issuing web requests can quickly become tedious, unless a helper library is used. \ For the examples in this article, I use the .NET Dream library (see sidebar "MindTouch Dream: A WOA-friendly Library"), which provides general-purpose classes for XML (XDoc) and web requests (Plug).

Listing 2 shows how we build the Atom entry corresponding to our work item. The library does most of the heavy lifting, making the creation of the XML document a breeze.

In the following code we submit the work item to the analyzer. The returned DreamMessage instance holds the HTTP response from the resource.

Plug p = Plug.New("http://server/analyzer");
DreamMessage response = p.Post(work);

Upon submitting the work item, the analyzer verifies that we have provided all the necessary information for it to proceed. If successful, we get a "201 Created" response indicating that our request resulted in the creation of a new work item resource and the Location header provides its URI. The analyzer also added several elements (shown in bold), which are expected of an Atom entry, such as when the entry was created, when it was updated, and how to interact with it (see Listing 3).

Editable vs. Read-Only Resources
The URI in the Location header tells us where to find our newly created work item. However, reading the work item and updating it are two different operations. Fortunately, Atom defines a way for an agent to discover if an entry can be edited. The following code shows the relevant XML element.

<link rel='edit' type='application/atom+xml'
href=' http://server/analyzer/789'/>

If we find this link element, we know that we can do PUT and DELETE operations on the associated URI to update or delete the work item. Otherwise, the resource is read-only and cannot be modified. This is a form of shared semantics between the resource and the agent that is provided by Atom.

The code snippet shows how we can use an XPath expression on the response XML document to retrieve the edit URI.

work = response.AsDocument();
XUri edit;
edit = work["link[@rel='edit']/@href"].AsUri;
if(edit != null) {
// we have an edit link!
}

Updating the Work Item
Now let's update our work item with extra information, such as the GPS coordinates of the image. Here are the coordinates in GeoRSS format:

<gps:point>45.256 -71.92</gps:point>

Using an XML namespace, we can add arbitrary information to Atom documents without interfering. The XML namespace guarantees that the names of XML elements will not conflict as long as the namespaces are different. Hence, adding the GPS coordinates is perfectly harmless. If the Analyzer understands them, it will take advantage of the new information, otherwise it will be ignored. This extension mechanism allows teams inside the enterprise to create new metadata annotations without having to coordinate on a central specification. With XML namespaces we can safely add new elements without conflicting with others. If the annotations are later superseded by alternatives, we can either use an XML transform or adapt the affected resources to look for both annotations.

Next, we add the XML namespace and element with the GPS coordinates to our work item representation.

work.UsePrefix("gps",
"http://www.georss.org/georss");
work.Elem("gps:point", "45.256 -71.92");

We are now almost ready to update our work item. Atom uses the PUT method to update an entry. However, before we can proceed, we must retrieve the value of the ETag header from the previous response. The ETag header can be thought of as a version token. In order for us to update our work item, we must have the correct ETag value and we must submit it with an If-Match header. This mechanism ensures that we don't accidentally modify a work item that was modified by someone. If that should happen, we will receive a "409 Conflict" response, indicating that we need to refresh our representation of the work item and resubmit the change with the updated ETag value if we still want to update it.

The following code shows the complete code to retrieve the ETag value, append the If-Match header, and issue our PUT request.

string etag = response.Headers.ETag;
response = Plug.New(edit)
.WithHeader("If-Match", etag)
.Put(work);

On success, the resource will respond with "200 Ok" and provide the updated ETag header so we may update the resource again:

200 Ok
Content-Type: application/atom+xml
Content-Length: ...
ETag: "456abc"
...

More Stories By Steve Bjorg

Steve Bjorg is the co-founder and CTO at MindTouch and the mind behind MindTouch Deki, the first WOA wiki platform. His work experience includes compilers, virtual machines, distributed systems, behavioral type systems, process calculi, and game development. Prior to MindTouch, Steve worked at Microsoft doing product incubation in the Advanced Strategies team.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.