Thursday, March 10, 2011

AtomPub Interface for Guvnor

I have been using Drools since the spring of 2008, when I first began working as part of a research team in Mexico. Over that period, I have explored some of the functionality within the platform, taking advantage of a few different projects (drools-expert, drools-planner and drools-guvnor) to help with my work here; creating software games based upon the participatory modeling our group does with rural people. Over the last 6 months, I have been working to make our newer games more open to changes and modifications by players on the ground and in realtime. To do this, I have implemented our latest game so it’s rules and object models are hosted by the Guvnor.

Over this time, I noticed that the Guvnor wants to work as part of a centralized workflow, such as that in a team-based rule editing and publishing process. This has made it somewhat difficult to adapt for the type of work involved in our gaming. For example, we want users to input new rules which modify social behaviors in the game; a process which is handled well by the 5.1.0 Guvnor. However, we also want the rule package compiled directly and available after such edits, possibly through our own interface, so all players in the running game are effected. To do this, I wanted a way to remotely invoke package compilation.

At RulesFest, in October 2010, I spoke with Esteban Aliverti and Mauricio Salatino, about my problem. Over the next few days we discovered a few others who also had an interest remote compilation and snapshot creation. I offered to add the required functionality, and was asked to log a JIRA issue.

I wrote-up GUVNOR-1080 and attempted to resolve what I needed through an “actions” API. Jervis Liu folded in the changes into the 5.2.0.M1 branch which enabled the following GET methods on the Guvnor webstack:Both require a “package-name” header (aka slug) to indicate which package to compile/snapshot. And both calls simply return a success report in the response (e.g., 204, 500). The compiled package or segregated snapshot are available through the customary Guvnor mechanism.

However, this was really not a satisfactory resolution of Guvnor-1080.

Further talk about the overall approach to REST access in the Guvnor project expanded from the JIRA issue, ad hoc discussions on the dev list to Jevis Liu’s “AtomPub Interface for Guvnor” proposal on the Drools community wikI. Taking off from where Michael Neale’s original “Guvnor AtomPub Interface” started in 2008 and expanding into categories, metadata and other return types, this page became a rough, but working implementation specification.

Implementation


Two main JAX-RS resources have been added to the Guvnor for use by REST based clients, these are the PackageResource and the CategoryResource.

All resources return and accept information in the following formats:
  • Application/Atom+XML
  • Application/JSON
  • Application/XML

Packages and Assets

The PackageResource allows clients access to packages and assets. The following methods are exposed via GET in the new REST based API for packages:Where “PACKAGENAME” means the package to be looked at and “ASSETNAME” means the asset. The following method is exposed via POST, and allows users to create new packages or assets:
Users need to push up either ATOM, JSON, or XML based content to create the package on the server, or use a DRL file in order to have the package created from that format.

The following methods are exposed via PUT, and allow users to update packages or asserts:
And the following methods are supported via DELETE:
Categories

Category access is only available for doing searches across the server based upon a specific category name. Results are returned in a paged format, and allow users to navigate across large datasets. The following GET methods are exposed for Categories:
Where “CATEGORYNAME” refers to an existing category on the server, and “PAGENUMBER” to the page number in the result set.

Idempotency


REST has certain guarantees regarding the idempotency of assets in GET, PUT, OPTIONS and DELETE methods. AS RFC 2616 states:
Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. [RFC 2616, page 50]
Idempotency in the Guvnor can only be guaranteed when working from a revision id perspective, not one based upon pure string based names, which is our current approach. As Guvnor front-ends a source control repository, queries to assets by name may only be IDEMPOTENT when said assets are addressed by their revision. Hence, although repetitive calls to GET, PUT, or DELETE are indempotent in context, actions by other users could update assets and packages so that calls will change over time.

Future


I’m anxious to hear from the community whether this implementation proves adequate. It could be a good idea to think about updating the GET methods with calls to Packages and Assets that are specific to a checked-in version in the Guvnor repository. It might also be a good idea to expand what gets serialized into the Package and Asset data from a given PUT or POST with an Atom/Json/XML entity. Finally, some more thought may be given to how metadata is handled, expanded and represented in the service.