In K2 2003 a user task was a good example where we often had routing logic in the workflow that had to be duplicated in the UI. For workflow routing our UI has to know what options the user had when auctioning a task and then the succeeding rule and all line rules out of the activity had to know about this as well. Maintenance was a nightmare.
In order to centralize routing logic, my team built a complete framework on K2.net 2003 that allowed us to automatically render the user interface for a workflow client event by looking at the available lines out of an activity that hosted the client event (if you are not bothered about the battles we had in 2003 or are a K2 blackpearl only client, skip to ‘In K2 blackpearl” sections).
In K2 2003
Here is the sample of the framework in action:
Logic of the workflow is automatically available in our business entities by purely inheriting from a specific base class (Customer in this example with an associated Customer Approval workflow instance) so accessing the logic defined in the workflow via client UI code looks like this:
' load a biz entity
Dim cust As Customer = _
RemoteServer.GeneralManager.Load(Of Model.Customer)(1)
' get the workflow context using the framework
RemoteServer.WorkflowManager.PopulateContext(cust)
' get the list of actions from the biz entity
For Each action As Action In cust.ActionsAvailable
Assert.IsNotNull(action, "bollocks test")
Next
' take the first action
cust.ActionToBeTaken = cust.ActionsAvailable(0)
' save the entity and action the workflow using framework
RemoteServerHelper.GeneralManager.SaveEntityObject(cust);
End Sub
Powerful feature, but because it is our own framework extensions on top of K2 2003, it is hard to maintain. For example, all our client events, lines, succeeding rules and line rules have to adhere to our framework requirements, i.e. “what action will lead to what line and what line represents a specific outcome”. We have to add and maintain XML stubs on all these entities, i.e. here is a line telling the framework what action will lead to its outcome:
Now that K2 blackpearl is available with the concept of being able to take a client action that leads to an outcome build into the product, life is much easier.
In K2 blackpearl
Blackpearl defines the concept of a client event in the workflow being aware of what actions can be taken on it. This is defined when creating the client even in the process designer. The wizard will also allow you to define outcomes and link the action that a user can take with a specific outcome based on your own rule set. Once the client receives the task at run-time, the task contains the available actions and the UI can automatically render this.
Here is a sample process:
When I added the client event, I automatically added two actions with two outcomes, North and South. I also asked the client event wizard to create a line for each outcome… not a single line of code needed for this.
Once I’ve started a new process instance and look at the allocated client task, I can see the two actions available: - this picture from the Workspace work list:
Job done! I can link these outcomes to my UI using either the various UI integration events available (InfoPath Client Event and Form Generation Client Event) – zero code required.
Alternatively I could render my own UI using the Client API. This sample code opens a connection to the K2 server, opens a task based on its serial number and then loops the available actions. It then takes the first action on the task in order to complete the client event:
static void LoadActions() {
// SourceCode.Workflow.Client.Connection now implements
// IDisposable...
using (Connection con = new Connection()) {
try {
// open connection and load task
con.Open("localhost");
WorklistItem task = con.OpenWorklistItem("SERIALNUMBER");
// loop the actions
foreach (Action action in task.Actions) {
Console.WriteLine(action.Name);
}
// action task (assume there is at least one)
task.Actions[0].Execute();
}
catch (Exception exception) { throw exception; }
finally { con.Close(); }
}
}
Thanks to the ambitions of the development team at Dynamyx that inspired the creation of the Dynamyx K2 framework that’s made life so much easier for us and our clients. I dedicate this blog entry to them. Rob, Ian, Trent, Kenny, Carlos and JT.