-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Occasionally you have a system which is coordinating activities between multiple parties. For example, filling your taxes may consist of the following steps:
- wait for your W2s and bank statements to arrive
- set up an appointment with your accountant
- wait for that appointment
- meet with him and get the paper work filled
- wait for rebate check
- cash check
In this example, this series of steps shows what an individual must perform to complete the process. It’s worth noting the steps alternate between an activity the individual performs, and waiting for some other party. The “workflow” problem ittyFlow attempts to address is how to model execution that contain points where execution is blocked, potentially for long periods of time.
IttyFlow provides a very light weight API to progmatically build and execute workflows as directed graphs.
The challenges are:
- The process is suspended and resumed frequently
- Information comes from the external participants
- Managing execution state
In software, this problem is often seen in building web applications. HTTP consists of individual requests, however, often a developer wants to provide the impression of a continuous session. When building an interface where one page depends on input from previous pages (such as a “wizard”) people often resort to building an adhoc workflow where the flow between pages is hardcoded onto each page.
Other implementations I’ve heard of that attempt to tackle this problem by modeling it as a graph with wait states are:
- Java Page Flow in WebLogic
- Spring Web Flow
- jBPM
Alternatively, one can model execution and persist continuations at each wait state — but that’s a story for a different time. (However, it’s a solution that I also like, but it has it’s own limitations)
Let’s formalize our vocabulary. Each one of these terms represents a class of entities which will need to be implemented for a workflow.
An Execution represents an evaluation of a workflow. Every execution represents a single evaluation of a particular workflow and at minimum has a reference to a wait state representing the current position in the workflow. You can think of this as a token that moves along the workflow.
Generally, the execution will also contain data that needs to be carried from one wait state to another. So, execution acts as the context in which all of the domain specific data is stored. For example, if you had a workflow defined for a store website where users add items to a cart and check out, the execution object would contain the contents of the cart so that it is retained as the user moves from page to page.
Represents what a execution is waiting for. These are generally implemented as an enumeration. The only hard and fast rule is that wait states should all be static final values. That being said, that means they can have any amount of (immutable) state associated with them as long the value is known statically.
Typical data associated with each wait state:
- name
- description
- what ActionBean to use to render the page if the user wants to see the current state of this execution.
It is important to note, there is no behavior in wait states. Wait states represent blocked execution, so they don’t do anything.
In a physical sense, a workflow represents a long running process that needs occasionally needs to wait for one or more actors.
The directed graph that represents all the possible paths an execution can take from one wait state to another. Workflow is a generic type which is parameterized by the execution and the transitions class.
In this directed graph, the vertices represent wait states and edges represent events. Movement along the graph is only allowed as a result of calling a method.
An actor is an entity outside of the workflow. All behavior and movement through the workflow is performed in response to actors. These actors pushes events into the system by use of the signal() method. There is no java class which needs to be defined for an actor.
From the perspective of the workflow, you can think of the universe as split into two parts: code that’s part of the workflow and code that is part of an external actor. Since there’s no implementation of an actor needed, there is no difference between a single actor firing events or multiple different actors firing events.
Examples of actors are:
- A user interacting on a web page.
- A notifier which is polling for new email.
Anything that calls signal() can be thought of as an actor.
- Domain specific execution state can be almost anything
- Show the big picture
- Lightweight
- Provide insolation between Actor facing interfaces and workflow
Event = method call that returns a “wait state”
Different events have different signatures
Events can be parameterized
First parameter is always task object
All execution takes place in response to an event, and may result in a state transition
Uses generics to parameterize over <WaitState, Transitions>
Instantiate and add states with associated event listeners
call signal(task) and the event to fire
Checks both start and resulting state validity against workflow
Automatically generates entered() events