about processes and engines

restful workflow engine (on Sinatra)


2010 update : this is an old post, the latest incarnation of this rest[ful] workflow thing is ruote-kit, and yes, OpenWFEru got renamed into ruote a while ago.


It may seem as an exercise, writing something restful. In the first take, I used Ruby on Rails to wrap OpenWFEru with a RESTful interface.

In this second take, I considered the alternatives among the Ruby web frameworks and went for Sinatra by Blake Mizerany.

Ruote-rest is mainly the result of a collaboration with a company which is integrating OpenWFEru (ruote) among its .NET applications. Its software artifacts speak XML over HTTP with ruote.

Ruote-rest, as a “take two”, is also the refinement of the concepts explored in the take one.

So what’s this RESTful workflow/BPM engine ?

It’s named “ruote-rest” and it’s available from GitHub at

It provides for now 3 resources, /processes, /participants and /workitems (and the special /expressions resource).

  • /processes – running [business] process instances
  • /participants – participants in the processes (out of the box there are two ‘worklist’ participants provided ‘alpha’ and ‘bravo’, but you can POST others and DELETE those)
  • /workitems – the workitems held by ‘worklist’ participants (for human consumption generally)

These resources are sufficient for

  • launching processes
  • fetching workitems, update their payload and let them resume in their business process
  • canceling part or all of a process
  • modifying a process on the fly
  • adding or removing participants to business processes

Ruote-rest currently provides two representations of its resources, an XML one and an HTML one. The XML representation is meant for automated consumption, the main case, while the HTML one is meant for learning / debugging.

The installation instructions are in the README.txt, and there is also a packaged release available.

— warning : boring technical post ahead —

a resource tour

Let’s have a look at ruote-rest once it’s running, through its ‘HTML interface’, which demonstrates the API ruote-rest exposes, via hyperlinks and forms.

GET /processes/processes enumerates the processes currently running in the engine.

New process instances can be launched (POSTed) with the form at the bottom of the HTML representation of /processes.

The form shows two ways of providing a process definition to the engine, via an URL (first input box) or by providing the process definition directly (text area).

Let’s just hit POST /processes.

Ruote-rest answers with an HTTP 201 reply containing a link to the newly created process instance. (The current HTTP status code is indicated on the top right of the HTML page, most of the time it’s at 200 OK).

Getting /processes/20080507-buparijitsu yields an HTML representation of the running [business] process instance (the workflow instance id being the 20080507-buparijitsu mentioned in the URI).

This page features links to all the expressions (/expressions/:wfid) that make up a process instance and to the JSON representation of the process definition itself.

It’s this representation that is interpreted in ruote-web when rendering graphically a process definition to some subset of BPMN. (Note that if the process instance got modified “en route”, it’s the process definition as running, not as launched which is returned).

There are two fat submit buttons, one for pausing (or resuming) the process instance (a PUT), and one for terminating (canceling) it altogether (a DELETE).

There is also a link to the “currently active expression” in the process (in other words, where the process is currently waiting). If there are concurrent execution paths for the process, there will be multiple “currently active expressions”.

A process instance is made up of expressions linked in an execution tree. The most common expressions are participant, sequence and concurrence.

The participant expression is used to link the execution of a workflow with an [external] participant, be it a service, a human, a small snip of code, …

OpenWFEru allows to modify the expressions in a running process instance. It may be necessary for administrative or business purposes (missing plan B maybe).

Expressions are stored in two states : unapplied and applied. Unapplied expressions have not yet been reached by the execution flow, they mainly are stored “raw”, uninterpreted (the whole branch they form with their unwound children expression).

The /expression/:wfid/:expid page features links back to the process and to the list of all expressions. There are also links to the parent expression, the environment expression (scope) and the children expressions, if any.

At the end of the page, there is a submit button for terminating the expression (cancelling it) (DELETE). If the execution path is located in the branch being terminated, the flow will be resumed after the cancelled branch.

By hitting the show link above the delete button, a text area containing the YAML representation of the expression will be displayed, along with a submit button for PUTting the updated expression back in the workflow engine.

That shows how to update business process instances, on the fly (this subject has been addressed for ruote-web in process gardening).

Ruote-rest, like ruote-web integrates a worklist for storing workitems for human consumption (not comestible though).

From the /workitems, the page for each individual workitem can be reached. It is also OK to query for the workitems belonging to just one process (/workitems?wfid=20080507-buparijitsu for example).

The HTML representation of a workitem has a text area containing the current payload of the workitem, as a JSON string, ready for being PUT back. If the “proceed” box is checked, the process will resume (with the updated payload).

The /participants page allows for addition / deletion of participants.

It currently only provides the way to add “active participants”, ie participants that place workitem in the integrated worklist. Other classes of participants can be added via the conf/participants.rb configuration file.

now and then

Ruote-rest is not finished. For example the /errors resource is not yet implemented (replaying a business process after an error is something important).

The initial representation is XML, along with HTML for educational purposes. JSON is a must. Why not some AtomPub like Kisha (the “take one” approach) included ?
Maybe YAML would be interesting too, for Ruby clients at least.

I’ve chosen Sinatra because I adhere to its convention :

get "/things/:tid" do
    "<p>I'm thing and my name is #{params[:tid]}</p>"

On the todo list is also some support for etags and if-modified-since, let’s make ruote-rest a good, respectful HTTP citizen.

The security stuff is rudimentary for now, here is how it looks :

# called before each request gets processed
before do

    throw :halt, [ 401, "get off !" ] \
        if request.env['REMOTE_ADDR'] != ''

The company for which ruote-rest is being specifically developed for doesn’t require any fancy auth mecha. But with Sinatra, they aren’t that far (see the so project for example or these posts).

Talking about security, the readers will certainly have noticed that the process definition can be fed directly into the engine, that’s very practical but you have to trust your auth mechanisms…

For persistence, ruote-rest currently uses the filesystem for the engine itself and a database (via Ruby on Rails’ ActiveRecord) for its worklist.

I’m thinking about integrating the automatic graphical process rendering found in ruote-web (ex-Densha) into the HTML “educational pages”, it would look good and help people understand what’s going on.

at the github

All this happens at, feel free to fork. Find the mailing lists at google groups.

Written by John Mettraux

May 7, 2008 at 8:49 am

Posted in bpm, openwferu, rest, ruby, workflow

2 Responses

Subscribe to comments with RSS.

  1. Very nice! And I learned a new HTTP code today… I guess I would have returned 301 or 302, not knowing about 201. Yup, it’s about time I start reading those 1992 specs ;-)

    Arjan van Bentem

    May 7, 2008 at 8:37 pm

  2. […] Looks neat but the interaction with the /tasks resource vanished, maybe I’ll be using the worklist embedded in ruote-web or ruote-rest. […]

Comments are closed.

%d bloggers like this: