EMF Workflow Model

I have been working on an EMF Workflow Model for some time now, and the documentation on how to use the model has been lacking.  In this post, I will show you how to extend and use the model with a complete example.  The EMF Workflow Model is a framework for modeling workflows.  Developers must extend the model by creating objects that do useful work.  Once the model has been extended, users may then assemble workflows from the components provided.  The core of the model is a composite pattern that allows a workflow to be constructed as an arbitrary tree forming a directed graph.  The framework supports executing nodes of the model in serial, parallel, loops, and conditionally.  Each node can be parameterized, and provides execution state that can be persisted.

There are two major parts to the workflow model:  a design model, and a runtime model.  The design model specifies which tasks to execute and the order they are executed.  The runtime model specifies the parameter values and state of the running workflow.  Separating the design model from the runtime model allows you to have a single workflow that can be executed with different permutations by choosing a different runtime model.

Workflow Design Model

The design model is based on a composite pattern (Figure 1).  The composite pattern allows for the construction of arbitrarily complex workflows.  Workflows can be a simple sequence of steps or a complicated tree of sub-workflows.  The flow of execution, or orchestration, is modeled as a strategy pattern (Figure 2). This allows custom flow control strategies to be plugged into the workflow providing a rich framework for executing workflows.  The framework includes strategies for executing workflow tasks in serial, parallel, conditionally, and in a loop.

Workflow

Figure 1

  • WorkflowComponent – the abstract root of the composite
  • CompositeWorkflowComponent – the branches of the tree
  • WorkflowUnitOfWork – the abstract leaves of the tree (you must extend this class)
  • WorkflowParameter – the keys of the runtime parameter map
  • WorkflowParameterConnection – connect an output parameter to one or more input parameters
Figure 2

Figure 2

  • WorkflowCompositeOrchestrationStrategy – abstract base class that controls the execution of children of a composite
  • WorkflowParallelOrchestrationStrategy – executes the children of a composite in parallel
  • WorkflowSerialOrchestrationStrategy – executes the children of a composite in serial
  • WorkflowComponentOrchestrationStrategy – base class that controls the execution of a component
  • WorkflowLoopComponentOrchestrationStrategy – executes a component in a loop
  • WorkflowExecutionPredicate – abstract base class for conditional predicates
  • WorkflowPredicateAND – logical AND of the child predicates
  • WorkflowPredicateOR – logical OR of the child predicates
  • WorkflowRerunPredicate – predicate based on the state of the last run
  • WorkflowParameterPredicate – predicate based on a parameter
  • WorkflowLoopCountPredicate – predicate based on a parameter value count

Workflow Runtime Model

The runtime model holds the dynamic information used by the workflow during execution.  This includes parameter values, execution state, and logging (Figure 3).  Parameter values are stored as instances of EObject allowing you to pass any modeled object to a workflow task.  Simple values such as String, Integer, etc can be wrapped in an instance of SimpleAnyType.  Since tasks can be executed in parallel, the runtime model makes use of EMF Transaction for thread safe access to the workflow data.  Workflow states are modeled using the state pattern (Figure 4).  You may extend a state if your task needs state granularity not currently provided.  You should not access the data in the WorkflowContext directly while the workflow is running, but instead use the convenience functions in the various design model classes.

Figure 3

Figure 3

  • WorkflowContext – the root container for all runtime data
  • WorkflowStateMap – maps a WorkflowComponent to a WorlflowState
  • WorkflowComponentExecutionInfoMap – maps a WorkflowComponent to a WorkflowComponentExecutionInfo
  • WorkflowParameterMap – maps a WorkflowParameter to its value
  • WorkflowLogMap – maps a WorkflowComponent to a WorkflowLog
Figure 4

Figure 4

  • WorkflowState – abstract base class for all workflow states
  • WorkflowIdleState – the task has not been executed
  • WorkflowDoneState – the task has finished executing
  • WorkflowRunningState – the task is currently running
  • WorkflowSuccessState – the task has finished successfully
  • WorkflowFailedState – the task has finished with a failure
  • WorkflowErrorState – the task has finished with an exception

Getting The Workflow Model

The model is contributed to the MWE sub-project under EMFT at Eclipse.org.  My contribution is not currently part of the MWE build, so you will have to start by extracting the model from CVS.  Start Eclipse and open the CVS Perspective.  Use the following connection:

  • Host: dev.eclipse.org
  • Path: /cvsroot/modeling
  • User: anonymous
  • Connection type: pserver

Expand the path: HEAD -> org.eclipse.emf -> org.eclipse.emf.mwe -> plugins and checkout the bundles org.eclipse.emf.mwe.ewm.*.  The org.eclipse.emf.mwe.core bundle contains the EMF model that you will extend.  The other bundles are primarily for convenience of experimenting with the workflow model.

Target Platform

The EMF workflow model requires the following projects in your target platform:

Extending The Workflow Model

Workflow tasks are domain specific and the EMF workflow model provides a framework for assembling and executing your domain specific tasks.  To use the EMF workflow model, you must extend WorkflowUnitOfWork to provide domain specific functionality in the run() function.  Use the following steps to create an extension to the workflow model:

  1. Create a new Empty EMF Project named org.example.workflow
  2. Create a new Ecore Model
  3. Load Resource… platform:/resource/org.eclipse.emf.mwe.ewm.core/model/workflow.ecore
  4. Create a new EClass
  5. Name: ExampleTask
  6. ESuperTypes: WorkflowUnitOfWork

EclipseNext, we need to create a genmodel and generate our code:

  1. Create a new EMF Generator Model
  2. Import from Ecore model
  3. Add org.eclipse.emf.mwe.ewm.core/model/workflow.genmodel as a referenced generator model
  4. Select both org.eclipse.emf.ecore and org.eclipse.emf.mwe.ewm.workflow as referenced generator models
  5. Suppress Interfaces: true
  6. Base Package: org.example.workflow
  7. Child Creation Extenders: true
  8. Extensible Provider Factory: true
  9. Generate Model Code
  10. Generate Edit Code

Eclipse 9

Eclipse 2

You will notice that ExampleTask does not compile.  The run() function in WorkflowUnitOfWork is abstract and where you need to add your domain specific business logic.  Open ExampleTask in the editor and choose the quickfix: Add unimplemented methods.  Go to the run() function and provide the following implementation:

@Override
public WorkflowState run(WorkflowContext context) throws WorkflowRuntimeException
{
	System.out.println("Hello world");
	return StateFactory.eINSTANCE.createWorkflowSuccessState();
}

Composing A Workflow

Now that you have a domain specific task that does useful work (“hello world” is arguably not useful – just envision a useful task), your task can be assembled into a workflow.  To do this, we will use the EMF generated editor to create an instance of the workflow model:

  1. Create a new Eclipse Application launch configuration
  2. Launch the runtime workbench
  3. Create a new General -> Project
  4. Create a new Workflow Model
  5. Select the root model object: Composite Component
  6. Set the name of the composite to Root
  7. Create a New Child of Composite Component: Workflow Serial Orchestration Strategy
  8. Create a New Child of Composite Component: Workflow Component Orchestration Strategy
  9. Create a New Child of Composite Component: Workflow State Resolution Strategy
  10. Create a New Child of Composite Component: Task
  11. Set the name of the task to Task
  12. Create a New Child of Task: Workflow Component Orchestration Strategy

Eclipse 4Every component must have an orchestration strategy.  In this model, there are two components: the root composite, and your example task.  Each of these components has a WorkflowComponentOrchestrationStrategy.  This strategy, by default, simply runs the component.  Every composite must have a composite orchestration strategy, and a state resolution strategy.  In this model, the composite orchestration strategy is WorkflowSerialOrchestrationStrategy which executes the children of the composite serially.  The WorkflowStateResolutionStrategy determines the state of the composite based on the state of the children after all of the children have executed.

Running A Workflow

To run the workflow you just assembled, you will need a runtime model and a launch configuration:

  1. Create a new Runtime Model
  2. Select the root model object: WorkflowContext
  3. Create a new EMF Workflow launch configuration
  4. Set Workflfow: platform:/resource/test/My.workflow
  5. Set Context: platform:/resource/test/My.runtime
  6. Launch the workflow

Run ConfigurationsAs your workflow executes, it will print “Hello world” to the console.  Don’t forget that the output will go to the Console view in the host workbench and not the runtime workbench.  There is an alternate way to run your workflow by right-clicking the workflow model and selecting Run Workflow.  You will be prompted to select the runtime model, the workflow will execute, and the runtime will be saved back to the workspace.  Note that the launcher will not save the runtime after execution.  After your workflow has terminated, you can view the contents of the runtime by right-clicking on the runtime model and selecting View Workflow Status.  You can reset the workflow runtime information by right-clicking on the runtime model and selecting Reset Workflow State.

Eclipse 5

Parameterizing A Workflow

Let’s make the workflow example task a bit more interesting by giving it a parameter for the message to print to the console instead of the hard-coded “Hello world”.  Change ExampleTask.run() to:

@Override
public WorkflowState run(WorkflowContext context) throws WorkflowRuntimeException
{
	System.out.println(getParameters().get(0).getValue(context));
	return StateFactory.eINSTANCE.createWorkflowSuccessState();
}

This will print the value of the first parameter assigned to the task. Before you can run the workflow, you must model the parameter, and give it a value in the runtime model.

  1. Launch the runtime workbench
  2. Open the workflow model in the ecore editor
  3. Create a new Workflow Parameter as a child of Task
  4. Set the parameter name to Message
  5. Set the parameter type to EString
  6. Create a new Parameter Simple Value Strategy as a child of the Workflow Parameter
  7. Open the runtime model in the ecore editor
  8. Load Resource … platform:/resource/test/My.workflow
  9. Create a new Workflow Parameter Map as a child of WorkflowContext
  10. Select Parameter Message as the key
  11. Create a new Simple Any Type as a child of the workflow parameter map
  12. Set the Instance Type to EString
  13. Set the Value to “That was easy”
  14. Run the workflow and “That was easy” will print to the host Console

Eclipse 6

Eclipse 7

Future Direction

This tutorial will eventually be moved into on-line documentation as part of the project.  The workflow model uses an explicit visitor pattern for some utility functions.  The switch object generated by EMF can be used as a visitor and I will probably look at using the switch object instead of the explicit visitor.  There is a need for the ability to run the tasks of a workflow on a distributed system.  I will be looking at adding the ability to suspend a workflow execution and transfer it to another machine for continued execution.  Finally, as you have seen from this tutorial, composing a workflow with the generated EMF editor is painful and a custom, structured, editor would make this easier.  Ultimately, I would like to have a graphical editor for visualizing and composing a workflow.  If there is any interest in contributing to this project, please contact me.

Advertisements

2 thoughts on “EMF Workflow Model

  1. Not to be critical – the work you’re doing is thoughtful and interesting. That said, I can’t help but think you’re heading down the wrong path by using a state machine based approach for workflow. You may disagree. I happen to agree with the premise put forth in Chapter 14 of Seam In Action:

    — Quote:
    When a business process is translated into an imperative language, such as Java, the big picture is quickly lost. This consequence is partially due to the fact that Java wasn’t designed to be represented graphically. The main reason, though, is that imperative languages typically operate using a brief, linear stream of execution (i.e., a thread). You already learned in chapter 11 that imperative languages aren’t well suited for the evaluation of rules; the better approach is a declarative language like Drools. The execution style of imperative languages is also at odds with business processes. Business processes are carried out in the real world where the speed of operation is many orders of magnitude slower than computer programs and where interruptions are commonplace. The result is that business processes spend more time waiting than executing.
    Imperative languages (without continuations, such as Java) don’t handle waiting
    well because they need somewhere to offload state held by the execution context when a wait is encountered. In addition negotiating a business process strictly in Java shifts the responsibility of establishing the correlation between nodes, and transferring state between isolated executions, on an external resource. It’s common to see developers write this state out to a file system or database so that it’s available on the next goaround.
    The result is a lack of clarity and no guarantee that the integrity of the process
    will be maintained. What you want is a continuous execution context that sits on top of Java and can be suspended and resumed freely. That describes exactly what jBPM provides.
    — End Quote

    My mind isn’t closed on the topic, but in my experience much of what he’s saying here rings true.

    Thoughs?

    Ron

  2. Pingback: Using EMF to Model Your Build Process as a Workflow « Miles To Code Before I Sleep

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s