The current landscape of workflow and business process management (BPM) solutions is extremely fragmented. Little concensus can be found in tools, specs and the academic community. The traditional approach has lead to monolithic, heavy-weight systems that have combined a lot of functionalities in a single system.
A missing feature in the Java programming language has led to a whole series of solutions in this space. This article will identify the missing feature and propose a simple solution for it called graph oriented programming. Graph oriented programming is to be seen as a common building block for workflow, BPM and orchestration solutions.
Let's start with a high level look at the current landscape of solutions in the fields of workflow, BPM and orchestration.
While there are no clear and general accepted definitions of workflow, BPM and orchestration, we can make some general observations.
Workflow is mostly related to the management of tasks for people. The core focus of a workflow process specifies tasks performed by humans are related to achieve a certain process goal.
Business process management, combines workflow with enterprise application integration (EAI). A business process specifies a combination of human tasks with pieces of software and how they are related to accomplish the business process goal.
Orchestration is mainly different by it's environment. Orchestration languages (like BPEL) are targetted towards a web service environment. An orchestration language is a programming language for (web) services. This means that you can write a new webservice by orchestrating other web services. Orchestration languages have control flow constructs as in regular programming languages. But the primitive operations are calls to other web services.
Now, we want to highlight a common aspect in these three fields. It is the ability to have wait states as part of the processes. Executions of these processes needs to suspend execution during the wait states.
Suspending an execution in java is not possible. Actually, it is possible to suspend and resume a thread in java (with e.g. Object.wait() and Object.notify()). But this does not match the needs for the process wait states because of persistence. Workflow, BPM and orchestration solutions need to persist their execution during wait states. In fact, state changes in a process should correspond to transactions on a server. Inbetween those transactions the suspended execution should be persistable in e.g. a database or on the file system.
Actually, it is not so surprising that java does not have a built-in mechansim for suspending and persisting executions. That is because java is built on top of the Von Neumann architecture. This essentially comes down to an environment for executing a sequence of instructions. This article presents a technique for extending the Von Neumann architecture for supporting the suspension and persistence of executions.
Products in the three fields have all solved this problem in their own way, from their own perspective. As a consequence, each solution combined a technique for suspending an execution with a whole lot of other functionalities. This is the fundamental reason why these topics are perceived as confusing and unclear by the development community.
One aspect is quite important and needs to be mentioned before we propose a solution for suspending an execution : Graphical representation of a process.
The technical ability to suspend an execution creates a very interesting opportunity : a direct link between the business process and the technical implementation. The business process is a central part of the requirements specified by the business analyst. Without a mechansim for suspending executions, the implementation of the business process requires a complex translation into a software design. In that case, the developer will have to store the executional state in some form in the database during wait states. This complexity is added and combined with the functional requirements of the business process.
The conclusion is that it would be great if we could find a solution for suspending an execution that is related to the graphical representation of a business process. Many (probably all) of the graphical representations of business processes are based upon a directed graph. Some of the process languages are limited to a tree which is a subset of a directed graph. Those languages are called block structured languages.
An important consideration is that the proposed solution should embrace iterative development. With UML class diagrams, this is an established practice. The analyst can draw an analysis model in an UML class diagram. Then the developer takes this model as a starting point and transforms it into a design model. Adding more technical details will result in an implementation. Too many proposed solutions ended up in being visual programming environments.
The traditional approach is to specify a process language as a set of constructs. Each construct has a graphical representation and a runtime behaviour.
There are substantial drawbacks to this generally used approach:
Graph oriented programming is a technique for solving problem of suspending and persisting an execution. Because of its limited scope, this technique, is easy to understand and serves as the building block for other functionalities targeted by workflow, BPM and orchestration solutions.
The central idea of Graph Oriented Programming is that a we complement plain imperative programming with a runtime model for executing graphs. So a graph is specified as part of the software and at runtime, executions of the graph are coupled to the execution of the imperative programmed software.
A process graph is made up of Nodes and Transitions. Transitions have a direction and connect two nodes in the graph.
The graph can be seen as a state machine. Although, the executional model that we will explain here is concrete and has better support for concurrent paths of execution.
The following UML class diagram sketches how the process elements can be modelled in an UML class diagram. This also shows that a process graph can be represented as data. The process graph data can be expressed in different formats : XML, java objects, records in a database,...
The next part is the most difficult part to understand for programmers and technical people. That is because we are specifying an executional model that differs from the well known Von Neumann architecture.
We define a Token as a path of execution. It's a path of execution within one system.
Note that an execution of a process can involve multiple concurrent paths of execution. We now define an execution of a process as a tree of tokens. A token has a pointer to a node in the process graph.
The following UML class diagram shows the tree of tokens modelled as a UML class diagram. This is included to show that an execution of a process can be represented as data. This is actually the crucial part of making an execution persistable.
Now, we'll explain how the execution of java can be coupled to the execution of the graph. The next image shows the methods in Node and Transition that are involved in graph execution. To calculate the next state of an execution, we propose a modified version of the chain of responsibility pattern as described by the GOF 'Design Patterns' book.
The Nodes in the graph can represent wait states. During a wait state, a Token points to that Node. Each Token that is in a Node can receive a signal. A Signal can be send to a Token to resume execution after a wait state is finished. This will cause the graph execution to start.
The effect of this signal is that the Token will leave the node. In case the node has more then one leaving transition, the leaving transition has to be specified as part of the signal. Transitions just take a Token to the destination Node. When a token arrives in a Node, the Node is executed. Each node in the graph is of a specific type that determines its runtime behaviour. Each node type corresponds to a subclass of Node and the behaviour is implemented in the execute-method.
The node's execute-method has 2 responsibilities. First, it can perform some business logic, related to the type of the node. E.g. sending a message, updating a database, creating a task for a user,... And the second responsibility of the node's execute-method is the propagation of the graph execution. If the node does not propagate the execution, it behaves as a wait state. It can propagate the token that arrived in the node down one of the leaving transitions. Or it can create new Tokens and propagate those down the leaving transitions.
Graph execution ends when all tokens have entered a wait state. At that time, the signal has been completely processed and the complete process execution (that is made up of a tree of tokens) enters a new overall wait state. At this time, the tree of tokens can be persisted. Each token is now waiting to receive another signal.
One crucial refinement of this model is necessary : Actions. Actions are pieces of java code that are executed upon events in the process. Examples of events are 'leaving a node', 'entering a node' and 'taking a transition'. These are all instantanious events that cannot span wait states.
The refinement of the graph execution model with actions is necessary because this allows the technical developer to add implementation details to the business process, without having to change the graph that was originally created by the business analyst.
Now we can summarize how this model solves the traditional problems of workflow, BPM and orchestration solutions.
The model that we have presented adds support for wait states to plain programming. With graph oriented programming we can now define paths of execution that span wait states. This model can be used as the basis for implementing workflow, BPM and orchestration functionalities.
Structured programming, Object Oriented Programming (OOP) and Aspect Oriented Programming (AOP) can all be seen as mechanisms to structure software. Graph Oriented Programming can also be seen as another mechansim to structure software. Adding structure to software is crucial for managing the complexity. Since the cost of software projects increases exponentially with their size, the cost savings of an extra mechanism to reduce the complexity can therefore be huge.