It’s been a while, and as usual Sensei has started something with such bravado and discovered that life offers more bluster and pounding than even he can anticipate. Hopefully you haven’t given up on the series, ’cause Sensei hasn’t. Hell, ApprovaFlow is constantly on the forefront, even though it appears that he’s taken a good powder.

Let’s recap our goals and talk about philosophy and direction. In this long silence a few additional considerations have taken precedence, and this is a good opportunity to assess goals and re-align the development efforts. In the end ApprovaFlow will:

• Introduce new functionality while isolating the impact of the new changes. New components should not break old ones

• Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user.

• Use one. aspx page to processes user input for any type of workflow.

• Provide ability to roll your own customizations to the front end or backend of your application.

The astute members of the audience will no doubt say “What about the technical objectives, like how are you going to store all the workflow data? In flat files? Will you give me alternatives for storage? How will I create the workflows, by using Notepad?” Indeed, Sensei has pondered these issues as well and has accumulated a fair amount failed experiments with some being quite interesting. Given time these little experiments may become posts as well, since there are interesting things to learn from these failures.

What ApprovaFlow Will Need To Provide: Workflow Storage

The biggest issue is storage. The point of using Stateless was that we wanted flexibility. Recall that the state of our state machine can be represented with a mere integer or string. Makes it pretty easy to store this in a database, or a document. While you could map the Step and Workflow class to tables in SQL our domain is using JSON so it makes sense to gravitate to a storage solution that will easily support that format. ApprovaFlow will use RavenDB as the document database, but will provide the opportunity for you to use a different solution if you wish. You’ll find that RavenDB quite readily provides a document storage format for our workflows that is quite elegant.

As an aside, Sensei experimented with a great alternative to the NoSQL solutions called Sis0DB. This open project provides you that ability to store you object graphs in SQL Server. Time permitting Sensei will share some of his adventures with you regarding this neat project.

What ApprovaFlow Will Need to Provide: Authorization of Actions

While Sensei was off in the weeds learning about RavenDB he discovered thatAyende created a fantastic mechanism for authorizing user actions on documents. This authorization of activity can be a granular as denying / allowing updates to occur based on an operation.

Since we want to adhere to principles of flexibility the Authorization features will be implemented as a plug-in, so if you wish to roll your own mechanisms to govern workflow approvals you will be free to do so.

What ApprovaFlow Will Need to Provide: Admin Tools

Yep. Sensei is sick of using Notepad to create JSON documents as well. We want to be able to create the states, the triggers and the target states and save. We’ll want to assign the filters to specific states and save. No more text fiddling. Period. As Sensei is thinking about this, it seems that another pipeline can be created for administration. Luckily we have a plug-in architecture so this should be rather straight forward.

Summing It All Up

These are really important things to consider, and as much as Sensei hates changing goals in mid stream the capabilities discussed above can make life much easier while implementing a workflow system. In making the decision to use RavenDB the thought that “a storage solution should not shape the solution domain” kept raising its ugly maw. But, so what. We want to finish something, and admittedly this has been a challenge – just look at the lag between posts if you need a reminder. If Sensei decided to include an IOC container just to remain “loosely” coupled to document storage we’ll get no where. Would you really want to read those posts? How boring. Besides, Sensei doesn’t know how to do all that stuf – gonna stick to the stuff he thinks he knows. Or at least the stuff he can fake.

This is the fourth in a series of posts for ApprovaFlow, an alternative to Windows Workflow written in C# and JSON.Net. Source code for this post is here.

Last Time on ApprovaFlow

In the previous post we discussed how the Pipe and Filter pattern facilitated a robust mechanism for executing tasks prior and after a transition is completed by the workflow state machine. This accomplished our third goal and to date we have completed:

• Introduce new functionality while isolating the impact of the new changes. New components should not break old ones

• Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user.

• Use one. aspx page to processes user input for any type of workflow.

• Provide ability to roll your own customizations to the front end or backend of your application.

It’s the Small Changes After You Go Live That Upset You

The goal we’ll focus on next is Introduce new functionality while isolating the impact of the new changes. New components should not break old ones, as it’s the small upsetters that lurk around the corner that your users will think up that will keep you in the constant redeployment cycle. If we implement a plug-in system, then we can prevent the new features from breaking the current production system. Implementing these changes in isolation will lead to faster testing, validation and happier users.

We lucked out as our implementation of the Pipe And Filter pattern forced us to create objects with finite functionality. If you recall each step in our workflow chain was implemented as a filter derived from FilterBase and this lends itself nicely to creating plug-ins. The Pipe and Filter pattern forces us to have a filter for each unique action we wish to carry out. To save data we have a SaveData filter, to validate that a user can supply a Trigger we have the ValidateUserTrigger, and so on.

“Great, Sensei, but aren’t we still constrained by the fact that we have to recompile and deploy any time we add new filters? And, if I have to do that, why bother with the pattern in the first place?”

Well, we can easily reduce the need for re-deploying the application through the use of a plugin system where we read assemblies from a share and interrogate them by searching for a particular object type on application start up. Each new feature will be a new filter. This means you will be working with a small project that references ApprovaFlow to create new filters without disturbing the existing architecture. We’ll also create a manifest of approved plug-ins so that we can control what is used and institute a little security since we wouldn’t want any plugin to be introduced surreptitiously.

Plug-in Implementation

The class FilterRegistry will perform the process of reading a share, fetching the object with type FilterBase, and register these components just like we do with our system components. There are a few additions since the last version, as we now need to read and store the manifest for later comparison with the plug-ins. The new method ReadManifest takes care of this new task:

The manifest is merely a serialized list of FilterDefinitions. This is de-serialized into a list of approved filters.With the approved list the method LoadPlugin performs the action of reading the share and matching the FullName of the object type between the manifest entries and the methods in the assembly file:

That’s it. We can now control what assemblies are included in our plug-in system. Later we’ll create a tool that will help us create the manifest so we do not have to managed it by hand.

What We Can Do with this New Functionality

Let’s turn to our sample workflow to see what possibilities we can develop. The test CanPromoteRedShirtOffLandingParty from the class WorkflowScenarios displays the capability of our workflow. First lets review our workflow scenario. We have created a workflow for the Starship Enterprise to allow members of a landing party to request to be left out of the mission. Basically there is only one way to get out of landing party duty and that is if Kirk says it’s okay. Here are the workflow’s State, Trigger and Target State combinations:

State

Trigger

Target State

RequestPromotionForm

Complete

FirstOfficerReview

FirstOfficerReview

RequestInfo

RequestPromotionForm

FirstOfficerReview

Deny

PromotionDenied

FirstOfficerReview

Approve

CaptainApproval

CaptainApproval

OfficerJustify

FirstOfficerReview

CaptainApproval

Deny

PromotionDenied

CaptainApproval

Approve

PromotedOffLandingParty

Recalling the plots from Star Trek, there were times that the medical officer could declare the commanding officer unfit for duty. Since the Enterprise was originally equipped with our workflow, we want to make just a small addition – not a modification – and give McCoy the ability to allow a red shirt to opt out of the landing party duty.

Here’s where our plugin system comes in handy. Instead of adding more states and or branches to our workflow we’ll check for certain conditions when Kirk makes his decisions, and execute actions. In order to help out McCoy the following filter is created in a separate project:

This plug-in is simple: check that the state is CaptainApproval and when the answer was “Deny” and Kirk has been infected, set the MedicalOverride flag and send Starfleet an email.

The class WorkflowScenarioTest.cs has the method CanAllowMcCoyToIssueUnfitForDuty() that demonstrates how the workflow will execute. We simply add the name of the plug-in to our list of post transition filters:

Now you don’t have to hesitate with paranoia each time you need introduce a variation into your workflows. No more small upsetters lurking around the corner. Plus you can deliver these changes faster to your biggest fan, your customer. Source code is here. Run through the tests and experiment for your self.

This is the third entry in a series of posts for ApprovaFlow, an alternative to Windows Workflow written in C# and JSON.Net. Source code for this post is here.

What We’ve Accomplished Thus Far

In the last post we discussed how Stateless makes creating a lean workflow engine possible, and we saw that we were able to achieve two of our overall goals for ApprovaFlow. Here’s what we accomplished:

• Model a workflow in a clear format that is readable by both developer and business user. One set of verbiage for all parties.
•. Allow the state of a workflow to be peristed as an integer, string, etc. Quickly fetch state of a workflow.

So we have these goals left:

•. Create pre and post processing methods that can enforce enforce rules or carry out actions when completing a workflow task. •. Introduce new functionality while isolating the impact of the new changes. New components should not break old ones •.Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user. •. Use one. aspx page to processes user input for any type of workflow. •. Provide ability to roll your own customizations to the front end or backend of your application.

Our next goal will be Create pre and post processing methods that can enforce enforce rules or carry out actions when completing a workflow task. We’ll use the Pipe and Filter Pattern to simplify the processing, and we’ll see that this approach not only streamlines how you handle variation in tasks, but also provides a clean method for extending our application abilities.

The advantage of breaking down the activities of a process is that you can create a series of inter-changeable actions. There may be some cases where you want to re-order the order of operations at runtime and you can do so easily when the actions are individual components.

Before we proceed applying the Pipe and Filter pattern to our solution, we need to establish some nomenclature for our workflow processing. The following chart lays out the vocab we’ll use for the rest of series.

Term

Definition

State

A stage of a workflow.

Trigger

A message that tells the workflow how to change states. If the state is “Phone Ringing” and the trigger is “Answer Phone” the new state for the phone would be “Off hook”.

StateConfig

A StateConfig defines a pathway or transition from one state to another. It is comprised of a State, the Trigger and the Target State.

Step

A Step contains the workflow’s current State. In the course of your workflow you may have many of the same type of steps differentiated by date and time. In other words, when you workflow has looping capability, the workflow step for a state may be issued many times.

Answer

The Step asks a question, waiting for the user response. The answer the user provides is the trigger that will start the transition from one state to another. The Answer becomes the Trigger that will change the State.

Workflow

A series of Steps compromised of States, Triggers and their respective transition expressed as a series of State Configs. Think of this as a definition of a process.

Workflow Instance

The Workflow Instance is a running workflow. The Steps of the Workflow Instance are governed by how the Steps are defined by a Workflow.

Essentially a framework for providing an extensible workflow system boils down to answering the following questions asked in this order:
• Is the user authorized to provide an Answer to trigger a change to the step’s State?
• Is a special data set required for this particular State that is not part of the Step properties?
• Is the data provided from the user sufficient / valid for triggering a transition in the Workflow Step’s State?
• Are there actions to be performed such as saving special data?
• Can the system execute custom actions based on the State’s Trigger?

This looks very similar to the Pipe and Filter pattern. Every time a workflow processes a trigger, the questions we asked above must be answered. Each question could be considered a filter in the pipe and filter scenario.

The five questions above become the basis for our workflow processor components. For this post we’ll assume that all data will be simply fetched then saved with no special processing. We’ll also assume that a Workflow Step is considered to be valid when the following elements are correctly supplied:

Our Workflow Processor will function in accordance with the Pipe and Filter pattern where no matter what type of workflow instance we wish to process, the questions that we listed above will be answered. Later we will return to discuss points of where the workflow can execute actions respective to the workflow’s definition.

Workflow Processor Code In Depth

Well, how do we configure a Workflow Processor? In other words, we want to process an actual workflow, but how will we know the workflow type and what to do? Some of configuration steps were previewed in Simple Workflows With ApprovaFlow and Stateless and the same principles apply here with the Configure method. Collect the States, the Triggers and the StateConfigs, load them into Stateless along with the current state and you are ready to accept or reject the Trigger for the next State. The Workflow Processor will conduct these steps and here is the code:

The Workflow Processor will need to know the current state of a workflow instance, the answer supplied, who supplied the answer, as well as any parameters that the filters will need fetching special data. This will be contained in the class Step.cs:

Our goal with the Workflow Processor is to accept the users answer, process actions, and create the next Step base on the new State all in one pass. We will create a pipeline of actions that will always be invoked. Each action or “filter” will be a component that performs and individual task, such as determining if the step is answered by the correct user. Each filter will point to the subsequent filter in the pipeline, and the succession of the filters can change easily if we see fit. All that is needed is to add the filters to the pipeline in the order we want. Here is the class schema for the Pipe and Filter processing:

We’ll quickly find that the information regarding whether the result of an action or the condition of a Step will need to be accessible to each of the filters. The class Step is the natural place to store this information, so we will include a property CanProcess to indicate that a filter should be invoked, as well a List<string> to act as an error log. This log can be passed back to the client to communicate any errors to the user. Note that the Step class has the Dictionary property named “Parameters” that allows a filter to pass data on to next filter in the sequence.

Setting Up the Pipeline

The sequence of filter execution is controlled by the order that the filters are registered. The class Pipeline is responsible for registering and executing the chain of filters. Here is the method Register that accepts a filter and retains it for future processing:

We also record the name of the filter so that we may interrogate the pipeline should we want to know if a filter has already been registered.

Pipeline.Register returns a reference to itself, so we can chain together commands fluently:

The class FilterBase is the foundation of our filter components. As stated earlier, each component will point the subsequent filter in the filter chain. You’ll note that the class also has a Register method. This takes on the task of point the current filter to the next, and this method is called by the Pipeline as it registers all of the filters. Here is FilterBase:

The method Execute accepts input of type T, and in the Workflow Processor instance this will Step. Basically the Execute method is a wrapper, as we call the abstract method Process. Process will be overridden in each filter, and this will contain the logic specific to the tasks that will be performed. The code for a filter is quite simple:

Here we check to see if we can process, then perform specific actions if appropriate. Given that the filters have no knowledge of each other, we can see that they can be executed in any order. In other words you could have a Pipeline that had filters Step1, Step2, Step3 and you could configure a different pipeline to execute Step3, Step1, and Step2.

FilterRegistry Organizes Your Filters

Because we want to be able to use our filters in different successions we’ll need to keep a registry of what is available to use and provide the ability to look up or query different filters depending on our processing needs. This registry will be created on application start up and will contain all objects of type FilterBase. Later we’ll add the ability for the registry to load assemblies from a share, so that you can add other filters as simple plugins. Information about each filter retained in a class FilterDefinition, and the FilterRegistry is merely a glorified List of the FilterDefintions. When we want to create a pipeline of filters we will want to instantiate new copies. Using Expressions we can create Functions that will be stored with with our definition for each filter type. Here is FilterDefinition:

FilterRegistry is meant to be run once at start up so that all filters are registered and ready to use. You can imagine how slow it could become if every time you process a Workflow Step that you must interrogate all the assemblies.

Once you FilterRegistry has all assemblies registered you can query and create new combinations with the method GetFilters:

Pipeline can accept a list of filters along with the string that represents the order of execution. The method RegisterFrom accepts a reference to the FilterRegistry along with the names of the filters you want to use.

In the case of the Workflow Processor, we need to divide our filters into pre-trigger and post-trigger activities. Referring back to our 5 questions that our processor asks, question 1 – 3 must be answered before we attempt to transition the Workflow State, while steps 4-5 must be answered after the transition has succeeded. The method ConfigurePipeline in WorkflowProcessor.cs accomplishes this task:

Putting It all Together

A lot of talk and theory, so how does this all fit together? The test class WorkflowScenarioTests illustrates how our processor works. We are creating a workflow that implements the process for a Red Shirt requesting a promotion off a landing party. You may recall that the dude wearing the red shirt usually got killed with in the first few minutes of Star Trek, so this workflow will help those poor saps get off the death list. The configuration for the Workflow is contained within the file RedShirtPromotion.json. There are a few simple rules that we want to enforce with the Workflow. For one, Spock must review the Red Shirt request, but Kirk will have the final say.

Study the tests. We’ve covered a lot together and admittedly there is a lot swallow in this post. In our next episode we’ll look at how to the Pipe and Filter pattern can help us with extending our workflow processor’s capability without causing us a lot of pain. Here’s the source code. Enjoy and check back soon for our next installment. Sensei will let you take it on out with this groovy theme (click play).

This is the second in a series of posts for ApprovaFlow, an alternative to Windows Workflow written in C# and JSON.Net. Source code for this post is here.

Last time we laid out out goals for a simple workflow engine, ApprovaFlow, with the following objectives:• Model a workflow in a clear format that is readable by both developer and business user. One set of verbiage for all parties.
•. Allow the state of a workflow to be peristed as an integer, string. Quicky fetch state of a workflow.
•. Create pre and post nprocessing methods that can enforce enforce rules or carry out actions when completing a workflow task.
•. Introduce new functionality while isolating the impact of the new changes. New components should not break old ones
•.Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user.
•. Use one. aspx page to processes user input for any type of workflow.
•. Provide ability to roll your own customizations to the front end or backend of your application.

The fulcrum point of all we have set out to do with ApprovaFlow is a state machine that will present a state and accept answers supplied by the users. One of Sensei’s misgivings about Windows Workflow is that it is such a behemoth when all you want to implement is a state machine. Stateless, created Nicholas Blumhardt, is a shining example of adhering to the rule of “necessary and sufficient”. By using Generics Stateless allows you to create a state machine where the State and Trigger can be represented by an integer, string double, enum – say this sounds like it fulfills our goal:

•. Allow the state of a workflow to be persisted as an integer, string. Quicky fetch state of a workflow.
Stateless constructs a state machine with the following syntax:

var statemachine =
new StateMachine(TState currentState);

For our discussion we will create a state machine that will process a request for promotion workflow. We’ll use:

var statemachine =
new StateMachine(string currentstate);

This could very easily take the form of

<int, int>

and will depend on your preferences. Regardless of your choice, if the current state is represent by a primitive like int or string, you can just fetch that from a database or a repository and now your state machine is loaded with the current state. Contrast that with WF where you have multiple projects and confusing nomenclature to learn. Stateless just stays out of our way.
Let’s lay out our request for promotion workflow. Here is our state machine represented in English:

Remember the goal Model a workflow in a clear format that is readable by both developer and business user. One set of verbiage for all parties? We are very close to achieving that goal. If we substitute “Step” with “State” and “Answer” with “Trigger”, then we have a model that matches how Stateless configures a state machine:

The next question that comes to mind is how to represent the various States, Triggers and State configurations as data. Our mission on this project is to adhere to simplicity. One way to represent a Stateless state machine is with JSON:

As you can see we are storing all States and all Triggers with their display names. This will allow you some flexibility with UI screens and reports. Each rule for transitioning a state to another is stored in the StateConfigs node. Here we are simply representing our chart that we created above as JSON.

Since we have a standard way of representing a workflow with JSON de-serializing this definition to objects is straight forward. Here are the corresponding classes that define a state machine:

We’ll close out this post with an example that will de-serialize our state machine definition and allow us to respond to the triggers that we supply. Basically it will be a rudimentary workflow. RequestionPromotion.cs will be the workflow processor. The method Configure is where we will perform the de-serialization, and the process is quite straight forward:

Deserialize the States

Deserialize the Triggers

Deserialize the StateConfigs that contain the transitions from state to state

We we have seen how we can fulfill the objectives laid out for ApprovaFlow and have covered a significant part of the functionality that Stateless will provide for our workflow engine. Here is the source code.

Like Tolkien, Sensei wants to create the landscapes, cultures and languages before he writes his next epic. You can be the judge whether the work is a series of sketches and notes like the Silmarillion or cohesive, compelling story that you want read again and again. As a bonus Sensei will deliver working software that hopefully will be of use to you. (Photo credit – utnapistim).

The epic will be called ApprovaFlow. ApprovaFlow is a framework / process / methodology that allows you to create workflow applications that are easy to deploy and are configurable. With ApprovaFlow Sensei hopes to demonstrate how to readily encorporate the inevitable changes that your users will ask of you. Deliver changes effortlessly and without groans. Cast off the chains inconvenient builds and focus on creating solutions that stay out of the users way.

• Model a workflow in a clear format that is readable by both developer and business user. One set of verbiage for all parties. •. Allow the state of a workflow to be peristed as an integer, string. Quicky fetch state of a workflow. •. Create pre and post nprocessing methods that can enforce enforce rules or carry out actions when completing a workflow task. •. Introduce new functionality while isolating the impact of the new changes. New components should not break old ones •.Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user. •. Use one. aspx page to processes user input for any type of workflow. •. Provide ability to roll your own customizations to the front end or backend of your application.

There it is. These goals will probably take us a good amount of time to review and implement. Is it worth it? Hell yeah. We’ll end up with one simple project instead of a bloated framework where it takes forever to find anything. A nice by product will be that you can spend more time thinking about how to solve your users problems rather than trying to figure out a monsterous framework that requires a huge investment of energy and time learning how to get simple things done.