Archive for K2

Accessing K2 API via K2 reference event

There is a way to access the K2 API from the reference event, although I will make the disclaimer that this is not supported in blackpoint. I will go over the steps of calling the GoToActivity method of the API from a reference event within the K2 designer.

Within K2 designer, you will need to drag a reference event onto the workspace. k2referenceevent

 

Configure an event name for the event, and after clicking next, you will come to a screen within the wizard to add a Constructor.

k2referenceevent_addevent

The next wizard you will want to click the “Add Reference” button and browse to “C:\Program Files (x86)\K2 blackpearl\Bin\SourceCode.Workflow.Management.dll” (if using a 64bit server). Select this DLL and add it to the list of available managed process references.

k2referenceevent_addref Click finish and then on the wizard where you select the constructor, expand the nodes as follows: 

SourceCode.Workflow.Management 
– SourceCode.Workflow.Management  
     – WorkflowManagementServer  

select Constructor(String host, UInt32 port).

k2referenceevent_addeventwms

 

For the configuration properties of the constructor, enter the following: 

host: value is the server name of K2 
port: value is the port that the K2 server is running on (typically 5555)

k2referenceevent_addeventwms_b

 

Once this constructor has been added, you will be brought back to the main wizard screen for the reference event and now it will allow you to add a Method event.

k2referenceevent_addmethodevent

After you click the add method option, you will need to expand the WorkflowManagementServer node and scroll down and find the method Open()

 

k2referenceevent_open Select Next and leave the default values for the configure properties and click Finish

 

 

 

Once more on the reference event main screen, click Add Method and expand out WorkflowManagementServer and find the method GoToActivity(Int32 procInstID, String activityName) : Boolean

k2referenceevent_goto

After clicking next, you will need to configure the method. The only values you need to worry about populating are the procInstID and activityName. 

procInstID – identifies the K2 process ID that you want to perform the GoToActivity method request. This values can be accessed many different ways. For my example, I stored the K2 process ID of my workflow in a SharePoint list and I called this workflow on the update of the list item (using the SharePoint event integration process within K2) and stored the ID in a data field. 

activityName – this field refers to the Activity in question that you want to “Go To”. If you reference the correct process ID, you can call an activity in any K2 process as long as you have the activity name correct. 

Click Next after configuring these 2 values, leave the connection properties as default (empty) and click Finish

k2referenceevent_gotoconfigure

 

k2referenceevent_finish

At this point, you are done configuring your Reference event and it should look like the screenshot to the left. Click Finish and you are done with the reference to the K2 API. Build and Deploy your process and test it out.

 

Working with Arrays in K2

I was asked recently how one can work with arrays in K2.  The specific scenario presented to me was where one had a SharePoint delimited values such as “7#;Acme Bank” into the individual elements.

This can be very easily handled with K2 Inline Functions.

FYI, you can use Inline Functions in nearly any wizard; they are accessed via the context browser here:

clip_image001

Ok, so how would we use Inline Functions to emulate the scenario below?  Attached is a simple self-contained example for your reference, but the highlights of it are:

  1. I created 3 process datafields
    • FullString – this simulates your SharePoint xml node, it contains a default value of: 7#;Acme Bank
    • ID
    • Value
  2. Drag out a Data Event onto the Design Canvas
  3. Select ‘Next’ on the welcome screen
  4. Select ‘Transfer Data’ on the 2nd dialog
  5. Click ‘Assign’ button
  6. In the ‘Destination’ field I drag “ID” from the Context Browser process datafields into it
  7. I select the Inline Functions tab in the Context Browser and then expand “Lists”
  8. I then select the “Index Item” method and drag and drop into the “Source” field
    • This will then open up a new dialog to configure the extraction of an array
    • I then set the following values:
      • Index:  1      (note:  in K2 arrays are 1 based not 0 based)
      • Expected when empty:   0
  9. In the ‘Values’ field I drag and drop the Inline Function Text > Split from the context browser
    • This will open up a new dialog to configure a string to be split into an array
    • I set the values of this Split dialog as follows:
      • Text:      [Process Data Field].FullString         (NOTE: you would use your xml field here)
      • Separator:           #;
  10. Click Ok
  11. Now repeat steps 5 – 10 but substitute:
    • In step 6:
      • Use ‘Value” process data field
    • In Step 8:
      • User Index of 2
  12. The final Data Event should look something like:

clip_image003

13. Save, deploy and run.  We should see the string split into individual values:

clip_image005

 

In addition to this scenario there are other usages potential usages for arrays in K2.  Such as:

– if a string held a delimited list of Domain\UserNames, one could use the Split Inline Function on that field within a Destination Rule in order to leverage generate a list of Destination Users.

– If a string held a delimited list of data for which sub workflows needed to be individually invoked in by an IPC event.  The Split Inline Function could be used within the Plan Per Slot – No Destination option of the Advanced Destination Rules.  For more information on Plan Per Slot – No Destination, which is essentially a For-Each loop within K2, please refer to this previous post:

http://www.k2underground.com/blogs/fromthebench/archive/2008/10/22/using-a-repeating-xml-node-to-start-child-ipcs.aspx

Creating K2 Environment Fields with Environment Library API

I know that you can use a deployment package to move environment settings to different servers, but I wanted to see if I can create them programmatically. The process of creating Environment Fields can be a time consuming and tedious task, especially if you have a large number of fields. Typically in a real-world project, a list of Fields are already defined in a functional document somewhere, so to have a utility which can create fields from a list in a text file for example could be a big time saver. At the time of this writing, documentation on how to do this kind of thing was rather scarce, hence this post 😉

The trick is to get a new instance of an Environment Field since is doesn’t have a new() constructor, you have to get a new instance by using the CreateFieldInstance() method of the EnvironmentFieldType class.

Steps:

  1. Create a new EnvironmentSettingsManager Instance and Connect to the K2 Server using the ConnectToServer() method of the EnvironmentSettingsManager instance.
  2. Create a new EnvironmentTemplateCollection Instance and a new EnvironmentInstanceCollection Instance.
  3. Select the Environment Template to use (e.g. Default Template) and select the Environment to use (e.g. Development)
  4. Get a handle on the EnvironmentFieldType you want to use by calling the EnvironmentSettingsManager.EnvironmentFieldTypes.GetItemByFriendlyName(“Miscellaneous Field”)
  5. Get a new EnvironmentField instance by calling CreateFieldInstance() method of the EnvironmentFieldType instance.
  6. Set the properties of the EnvironmentField instance
  7. Add the Field to the EnvironmentFieldCollection of the Environment Instance with the Add(newField) method of the EnvironmentFieldCollection
  8. Call the SaveUpdate() method of the EnvironmentField

Code:

EnvironmentInstance ei = new EnvironmentInstance();
ei = eic.GetItemByName("Development");
esm.ChangeEnvironment(ei.EnvironmentId);
EnvironmentFieldType eft = esm.EnvironmentFieldTypes.GetItemByFriendlyName("Miscellaneous Field");
EnvironmentField ef = (EnvironmentField)eft.CreateFieldInstance();
ef.FieldName = "DeonTestField";
ef.FieldDescription = "Deon Test Field";
ef.DisplayName = "DeonTestField";
ef.Value = "Some Value in Here";
efc = new EnvironmentFieldCollection(ei);
efc = ei.EnvironmentFields;
efc.Add(ef);
ef.SaveUpdate();