My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
WAG_RFC_001  
Heuristic Request/Response Mappings
Updated Nov 2, 2007 by ted.husted

THIS IS AN INCOMPLETE, WORKING DRAFT DOCUMENT FOR DISCUSSION PURPOSES ONLY.

Heuristic Request/Response Mappings

Working Draft 31 October 2007

Document ID: WAG_RFC_001
Previous Versions: None
Editors: Ted Husted; <Others TBD>

This document is currently a working draft published with the intent of soliciting community feedback. Please send your comments and concerns to the public mailing-list: web-alignment-group@googlegroups.com.

This document is designed to provide the developer with the information needed to implement the technology within a web development framework for any platform.

1. Overview

"Heuristic Request/Response Mappings" is a technology that combines intelligent defaults, convention over configuration, and annotation, in order to streamline web application development.

In a Heuristic workflow, the client requests a virtual "action" URI, often via an HTML form, which the system automatically maps to a code-component. (In a Java implementation, for example, a code-component would be a Java class.) The code-component is invoked, and the system selects a view-component (e.g. a JSP template) based on a heuristic that utilizes the original action URI and a result token provided by the code component.

Optionally, metadata, in the form of inline annotations or external XML documents, may be used to override the components usually mapped to an action URI or action result. Although, most common application workflows can be realized without resorting to metadata.

1.1. Goals

The primary goals of this memorandum is to define the Heuristic Mapping technology in terms of:

  • Heuristic Action Matching - selecting a code-component based on an action URI.
  • Heuristic Result Matching - selecting a view-component based on an action URI and a code component result token.
  • Explicit Mappings - overriding component selections with metadata settings.

A secondary goal is to also define an approach for

  • Mapping RESTful URIs to Heuristic URIs.

1.2. Non-Goals

The Heuristic Mappings technology does not address issues such as validation, security, session management, or the generation of a response to common errors, such as "File not found". Developers are expected to utilized existing features found in the underlying platforms to implement such features.

1.3. Limitations

TODO

2. Differences From Prior Versions

None.

3. Requirements

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY and OPTIONAL in this document are to be interpreted as described in RFC 2119.

An implementation is not compliant if it fails to satisfy one or more of the MUST requirements for the patterns it implements. An implementation that satisfies all of the MUST and all of the SHOULD requirements for its features is said to be unconditionally compliant; one that satisfies all of the 'must' requirements but not all of the SHOULD requirements for its features is said to be conditionally compliant.

4. Terminology

This section contains a summary of some terminology used elsehwere in this documentation that can help in disambiguation of commonly applied and therefore often overloaded terms. It may help to read other sections

* Indicates that a term relates to a setting with a default value that may be changed by a runtime system or implementation.
Action Request/Response A named operation supported by the application that expects zero or more input parameters and ultimately returns a response to the client, usually in the form of a HTML page.
base-code-prefix A set of string tokens, expressed as a space-delimited list, that are perpended to a potential code-component-name. The default code-prefix is "actions.", which, for the Java platform, would map to an "actions" package. *
Base Scope Strategy See section 5.1.2.
candidate-name The matching heuristic will apply a series of transformations to a name token, selecting the first form that matches. Each form instance is referred to as the candidate-name.
candidate-prefix During processing, the mapping-path is transformed, and the transformed version is referred to as the candidate-prefix
Client The agent that initiates the action request and receives the action response.
code-component-name The formal name on the target platform for a block of executable logic. For Java or .NET, this would be a class name.
code-component A software component that executes business logic or data access logic as part of an Action Request/Response initiated by a Client. Depending on platform, this may be a Java or .NET class, or a PHP or JavaScript function.
code-separator-character Some platforms organize code-components into a hierarchy of packages, namespaces, or modules. The code-separator-character is used to punctuate the hierarchy. The default setting is the dot "." character, which is used by the Java and .NET platforms. *
code-suffix A string token appended to the end of a potential code-component name. The default suffix is "Action". A code-component is not required to utilize a suffix or to implement any special interfaces or protocols. *
Code Suffix Strategy See section 5.1.1.
base-code-component A code-component provided by the implementation to be utilized when a custom code-component is not provided by teh application. The default name is "BaseAction". An implementation must provide a default code-component, even if it is a no-op method or function. *
mapping-name The part of a URI that will correspond to the name of an operation.
mapping-path The portion of a uri-path that precedes the mapping-name.
Method Matching Strategy See section 5.1.3.
path-segment A portion of a uri-path as defined by RFC 3986
path-separator The slash ("/") character, as defined by RFC 3986.
SEO Search Engine Optimized.
System The software component (e.g. web application framework) that implements the Heuristic Mappings technology described by this document.
to-code-name-transformations A series of platform-specific changes that are made to convert a mapping-name into a candidate-name. *
to-code-prefix-transformations A series of platform-specific changes that are made to convert a mapping-path into a candidate-prefix. *
uri-path A segment of a URI as defined by RFC 3986.
view-component A page template or similar component that is responsible for rendering a response to a client's request.
word-separator-character A mapping name may contain one or more semantic "words" which are punctuated with this character. The default setting is the hyphen ("-"), which is SEO compliant. *

5. Heuristic Action Matching

Larger applications tend to the separate the concerns of "business logic" and "display logic" into different components. Often, explicit metadata settings, either in XML or annotation, are used to assemble these concerns back into a single request/response transaction,

While the individual metatadata settings are simple, in larger applications the sheer number of settings become both a development and maintenance burden.

Heuristic Mappings assemble separted concerns back into a unified workflow without requiring redundant metadata settings. The heuristics are designed to observe conventions that are natural to developers and follow common organization patterns.

5.1. Strategies

The heuristics utilize three key matching strategies: Code Suffix, Base Scope, and Method Matching

5.1.1 Code/View Prefix Strategy

TODO: This is the most important strategy, and the poorest explanation :)

Developers tend to group code-components and view-components into a number of common "scopes". For code-components, these may be "packages" or "namespaces". For view-components, these may be a base folder for page templates.

The Code/View Prefix Stategy lets use specify one or more base scopes or prefixes. When matching a component, the heuristic transforms the mapping-prefix into a code-prefix (package name) or a view-prefix (folder name), and prepends the base-code-prefix or base-view-prefix.

If the mapping-prefix contains multiple path-segments, then each path-segment is tried in turn, longest to shortest. If there is more than one base-code-prefix or base-view-prefix, each is prepended to the candidate mapping-prefix in turn.

5.1.1. Code Suffix Strategy

All of the heuristics are based on the tendency of developers to name related constructs alike. The system provides a code-suffix ("Action") so that a "PersonAction" component can be kept with a related "Person" component. If a "PersonAction" isn't found, the heuristic looks for a "Person" component instead.

5.1.2. Base Scope Strategy

Developers often refactor shared functionality into base components. Accordingly, the system can check a more specific location first, and the falls back to check a base location. If a component can be used by more than one workflow, it can be stored in a base location. The base-scope strategy can be applied to both Code Components and View Components.

5.1.3. Method Matching Strategy

If a multi-word component isn't found, the system can also check whether the final word is the name of a method. The method-matching strategy gives developers the flexiblity to serve multiple action URIs from a single component.

5.2 Formal Descriptions

To describe the heuristics, we provide both an Example section and an Explanation section. To help illustrate both the Example and the Explanation, a BNF-style grammar (BNF-1) is provided, with some common extensions.

| alternatives
optional
{} repeats zero or more times
+ item repeats one or more times
* item repeats zero or more times

5.2.1 Example

Given the uri-path

  • /nested/namespace/my-resource.action
and the default
<code-suffix>
of "Action", a Java implementation will first try to match "/nested/namespace/my-resource" in the Explicit Mappings. If it is not found, then the implementation will try to match in sequence the candidate-names:

   1. MyResourceAction
   2. MyResource
   3. MyAction.resource()
   4. My.resource()
   5. my.resource/IndexAction
   6. my.resource/Index
   7. or utilize the default code-component (!BaseAction)

At each step 1-5, for our given URI path, the implementation scans

   1. Each <base-code-prefix> plus "nested.namespace." plus <candidate-name>
   2. Each <base-code-prefix> plus "nested." plus <candidate-name>
   3. Each <base-code-prefix> plus <candidate-name>

Given a

<base-code-prefix>
setting of "actions.", the system will try to match

   1. actions.nested.namespace.MyResourceAction
   2. actions.nested.namespace.MyResource
   3. actions.nested.namespace.MyAction.resource()
   4. actions.nested.namespace.My.resource()
   5. actions.nested.namespace.my.resource/IndexAction
   6. actions.nested.namespace.my.resource/Index

and then

   7. actions.namespace.MyResourceAction
   8. actions.namespace.MyResource
   9. actions.namespace.MyAction.resource()
  10. actions.namespace.My.resource()
  11. actions.namespace.my.resource/IndexAction
  12. actions.namespace.my.resource/Index

and finally

  13. actions.MyResourceAction
  14. actions.MyResource
  15. actions.MyAction.resource()
  16. actions.My.resource()
  17. actions.my.resource/IndexAction
  18. actions.my.resource/Index

returning either the first match found, or the default component (BaseAction).

An implementation should add found matches to the Explict Mappings (see Section 7) under the original uri-path ("/nested/namespace/my-resource"), so that a heuristic search does not need to be repeated each time.

5.2.2. Explanation

Heuristic Action Matching is applied to the path of a URI, as defined by RFC 3986. In a URI, a path consists of a sequence of path segments separated by a slash ("/") character, which acts as a path-separator.

<uri-path> ::= {<path-segment>} | {<path-separator> <path-segment>}

The system extracts the final path segment as the "mapping-name". The remainder of the path, if any, is considered the "mapping-path".

<uri-path> ::= {<mapping-name>} | {<mapping-prefix> <mapping-name>}

The system may apply a series of transformations to the mapping-path. The "to-code-prefix-transformations" may vary by platform. The default transformations for the Java platform are provided as an example.

 1 The mapping-path is copied as the candidate-prefix
 2 The candidate-prefix is converted to lower case 
 3 The path-separator-character ("/") is replaced by the code-separator-character (".") 

On the target platform, the system utilizes the candidate-prefix as a "package" or "namespace" when matching the mapping-name with a code-component-name.

The mapping-name may contain one or more semantic "words", separated by a word-separator-character. The default character is the hyphen ("-").

To match the mapping-name to a code-component-name, the system may apply a series of transformations to the mapping-name. The to-code-name-transformations may vary by platform. The default transformations for the Java platform are provided as an example.

 1 The mapping-name is copied as the candidate-name
 2 The candidate-name is converted to lower case 
 3 Any letter immediately following any word-separator is converted to upper case
 4 The word-separator is removed (spliced) from the candidate-name
 5 The initial character is covered to upper case
 6 The code-suffix ("Action") is appended to the candidate-name

The system may provide the base-code-prefix as a list. The implementation must scan each base-code-prefix with-and-without the candidate-prefix. The overall search pattern could be expressed as:

<uri-path> ::= {<mapping-name>} | {<mapping-prefix> <mapping-name>}
<candidate-prefix> ::= (to-code-prefix-transformations) <mapping-prefix>
<candidate-name> ::= (to-code-name-transformations) <mapping-name>

<search-prefix> ::= \[<base-code-prefix>*\] \[<candidate-prefix>\]
<search-action> ::=   {<search-prefix>} <candidate-name>{<code-suffix>} 
<search-method> ::= | {<search-prefix>} <candidate-name-word-1:N>{<code-suffix>}.<candidate-name-word-N> 

Finally, the search-prefix heuristic is repeated for each path-segment in the candidate-prefix, longest to shortest.

For each base-code-prefix (but only until a match is found), the implementation

1 Must scan in each base-code-prefix for a code-component that matches the candidate-prefix prepended to the candidate-name (//my/example/HelloWorldAction).

2 Must truncate the code-suffix ("Action") and try (1) again (/**/my/example/HelloWorld).

3 Should check whether the original identifier contains one or more word-separators, If so, the implementation should truncate the final word of the original identifier, append the code-suffix ("Action"), and scan for a matching component (per (1) and (2)) with a method (function, or procedure) that matches the truncated word (/**/my/example/HelloAction.world).

4 Should repeat (1)-(3) for each path-segment the candidate-prefix (/**/my/HelloWorldAction and /**/HelloworldAction). The no-path-segment case is always tried last, if no other match has been found.

5 Must utilize the default code component and default result type (BaseAction.success) when no other code component is matched.

Note that (5) guarantees that each request/response workflow will utilize a code componenet, even if it is a no-op component.

The system instantiates the matched code component, and invokes the default method ("success") or an explicit method, if so configured. If no explicit method is specified, and the code component does not contain the default "success" method, no method is invoked, and the default result code ("success") is utilized.


6. Heuristic Result Matching

TODO

7. Explicit Mappings

TODO

8. Processing a Request/Response

TODO

9. Naming Artifacts (URIs, actions, results, parameters)

TODO

10. Mapping RESTful URIs to Heuristic URIs.

TODO

11. References

12. Bibliography

12.1 REST Bibliography

the Design of Network-based Software Architectures] (Fielding's REST Dissertation)

####


Sign in to add a comment
Powered by Google Project Hosting