How To: Configure and use the "Wait for External System" option in a workflow
This topic shows you how to configure and use the Wait for external system option in a SmartObject workflow event.
The Wait for external system option (sometimes also referred to as an asynchronous server event) provides a way of pausing a workflow and waiting for an external application to finish doing something. Essentially, it is like assigning a task to a system, and the workflow will wait for that system to finish its work before continuing. External events are sometimes unpredictable in terms of how long they might take to complete, and by using this option, you can configure your workflow event to wait until the external system confirms that it is finished. Your workflow will not continue on to the next workflow step until the event completes. The external event in this example uses the workflow REST API to communicate with K2, but you can also use the workflow client API.
To configure this feature in the workflow, check the Wait for external system check box in the Options section of the configuration panel on a SmartObject step. You will use the SmartObject input mappings to pass the unique workflow step serial number (SN) to the external system. The external system needs to use this Serial Number to connect back to K2 and tell K2 which workflow instance to carry on with. The external system can also use the SN to open the workflow and set workflow variables values, before telling K2 to complete the SmartObject event.
As an example, you might have a sales order process, where the workflow calls an external service to place an order. The external service can take hours to complete their part of the order request before sending back a confirmation. It would be inefficient to poll the external system to determine if the order is processed; the "Wait for External System" option would be more efficient. You would configure the Wait for external system option on the SmartObject that represents the external service, which pauses the workflow until the external system confirms the order is processed by calling back to the K2 server with the serial number. The Sales Order workflow continues once it has received confirmation from the external system that the order was processed.
Configuring the "Wait for External System" option
Using the Wait for External System Option
To help you learn how to use the Wait for External System option, you can follow the steps below that describe how to implement a sample scenario. You can either build out the solution from scratch, or download and deploy the sample project described by these steps.
This sample project consists out of a SmartObject, workflow, external app and external code (REST API / Client API). Click here to download the WaitForExternalSystemSample.zip solution. The solution includes the following:
- External system Sample App is the compiled ExternalSystemSample Application that you run
- External System Sample Source is the source code for the app that you can edit and recompile, if needed
- External system Sample K2 Package which contains the K2 SmartObject and the workflow
Steps
In this step, you create and configure a workflow called Sample External System Workflow and configure workflow permissions.
- From the K2 Designer locate All Items > K2 Documentation and right click the Workflows category. From the menu, select New Workflow.
- Name this workflow Sample External System Workflow and click Create.
- You start this workflow manually so no configuration is required on the Start step.
You may notice a yellow warning indicator on the Start step and a corresponding warning message in the error console. This warning indicator is a visual reminder that you have not configured how your workflow starts. The warning indicator goes away as soon as you select a start option and does not stop you from deploying your workflow. For more information about the yellow warning indicator, see the Why do I have a yellow indicator badge on my Start Step? section in the Start step topic. In this example, no configuration is required.
- From the Toolbox, click the Basic category and drag the SmartObject Method step onto the canvas. Change the step name to Wait On External System.
This SmartObject sends information to the external system and waits for the external system to send a message back to continue with the workflow. The Status field is set to "Waiting" and the workflow Step Serial Number is sent to the external system to use in the Finish method call.
- Select the Smart Object Method step, and then select External System SmartObject. This SmartObject contains the contact ID, Status, and the Step Serial Number information. From the Method menu, select the Create option.
- In the Input Mappings section, add the Step Serial Number and Status properties. Expand the Context Browser and from the Workflow Step properties, drag and map the Serial Number property to the Step Serial Number property. Type Waiting as the Status property value.
Serial Number is the important part here: remember that this is the value that the external system will have to use to connect back to K2 and tell the workflow to continue.
- In the Output Mappings section, select the Create a Reference option and click Create. This creates the External System SmartObject reference which you can then use later on in the workflow.
For more information on configuring the SmartObject step, see the SmartObjects Overview topic. - Scroll down and expand the Options section. Check the Wait for external system check box. When the workflow reaches this step, the Status changes to Waiting and the workflow waits for the external system to complete and send back a success status to the workflow.
- In order to capture the completed status, you can create variables in the workflow to capture data returned from the external system. Here we will just add one sample datafield that the external system will set. From the Context Browser, click Add and add a text variable called ExternalAppResponse.
- Now we will add some workflow logic to follow a different path, based on the variable that was set by the external system. From the Toolbox, click the Logic category and drag the Decision step onto the canvas and connect it to the Wait On External System SmartObject Method step. Change the step name to Evaluate External Response.
After the external system sends the message to finish, the Wait On External System SmartObject step, it passes back a response through the variable called ExternalAppResponse. A custom decision rule on the decision step then sends the workflow either in the Success or Fail path based on the response from the external system.
- Select the Decision step and expand the Configuration Panel. Add Success and Fail as the two decisions paths.
- Select Custom Rule and click Edit Decision Rule.
- Use the ExternalAppResponse variable to specify which path is followed based on the data received from the external system. In this example, the workflow follows the Success path if the value from the external system is Success.
- From the Toolbox, click the Basic category, drag the SmartObject Method step onto the canvas and connect it to the Success path. Change the step name to Set Status Processed - Success.
This SmartObject sets the Status property to Processed - Success.
- Select the Smart Object Method step, and then select External System SmartObject. From the Method menu, select the Save option.
- In the Input Mappings section, add the ID and Status properties. Expand the Context Browser and the External System SmartObject Reference. Drag the ID reference into the ID property. Type Processed - Success as the Status property value.
- From the Toolbox, click the Basic category, drag the SmartObject Method step onto the canvas and connect it to the Fail path. Change the step name to Set Status Processed - Fail.
This SmartObject sets the Status property to Processed - Fail.
- Select the Smart Object Method step, and then select External System SmartObject. From the Method menu, select the Save option.
- In the Input Mappings section, add the ID and Status properties. Expand the Context Browser and the External System SmartObject Reference. Drag the ID reference into the ID property. Type Processed - Fail as the Status property value.
- Select the File menu and Deploy the workflow.
- After successful deployment use the manage permissions... link and navigate to K2 Management to set the workflow rights.
- On the Workflows tab select the Sample External System Workflow and click Rights.
- Click Add to add more users and set workflow rights for the added user. In this example Codi Kaji is added and granted Start and View rights on the Sample External System Workflow. For more information on workflow rights, see the K2 Workflow Designer Permissions topic.
In this step, you will create the code that will tell K2 to complete the waiting SmartObject step. You add code to enable the communication between the external system and the workflow. After the external system gets the call to perform whatever it needs to do from the SmartObject, and it completes its work, it must tell the K2 workflow that it is done. It does this by using the SmartObject step serial number (SN).
Knowledge of Visual Studio, JSON, and the REST API is required to fully understand and implement the steps in this part. It contains illustrations for how to enable the workflow REST API endpoints and the code necessary from the external system to communicate back to K2.
- If you want to use the Workflow REST API to write code that tells K2 to complete the waiting event, you will first need to enable the Workflow REST API if it is not yet enabled.
You enable this feature to expose the endpoints to manage workflow, workflow instances, and tasks/. (For more information on configuring the Workflow REST API, see Configure the Workflow REST API.)
From K2 Management browse to Integration > API's > Workflow REST. Click the slider to enable the Workflow REST API. - The enabled Workflow API shows.
- Click Open Link to open the K2 Workflow API Swagger page and access the list of operations, tasks, and workflow functions.
- To successfully integrate a workflow with an external system and pass data back into your workflow, use the POST serverEvents/{serialNumber}/finishmethod of the ServerEvents operation. This function completes the server event using a serial number. You can also supply values for data and XML fields, or Item References, using JSON.
- Use the Try It Out! button on the Swagger page to familiarize yourself with the endpoint functions.
For more information on the Swagger URL, see the Swagger URL section in Configure the Workflow REST API. - Now you can write the code that actually calls the REST API to complete the waiting event, You must include the step's serial number within the finish endpoint path.
Example: https://[K2 SERVER URI]/api/workflow/[VERSION]/serverEvents/" + stepSerialNumber + "/finish- [K2 SERVER URI] is the URI to you K2 environment. You can get this value from the page where you enabled the Workflow REST API.
- [VERSION] is the REST API version (typically "v1" but can be "preview" depending on your version of K2). This is found in the K2 Management site in the REST integration settings. For more information see the Workflow REST API Version section in Configure the Workflow REST API.
- stepSerialNumber is the serial number of the K2 workflow step that is waiting on the external application to complete. Use this in the URL path for the REST endpoint.
You can also set the value of a workflow variable. In the code sample below, we set returns a Success or Fail message back to the workflow into a variable called ExternalAppResponse. In this example, the URI part datafields is used to send a response back to the K2 workflow using a variable named ExternalAppResponse. The values is either Success or Fail.
/// This method uses the serverEvents REST endpoint to finish an Asynchronous SmartObject event. Include the Step serial number within the
/// "finish" endpoint path.
/// e.g. https://[K2 SERVER DOMAIN]/api/workflow/[VERSION]/serverEvents/" + stepSerialNumber + "/finish"
/// - [VERSION] is the REST API version, which may be something like "v1" or "preview". This is found in the K2 Management site under the REST
/// integration settings.
///
/// NOTE: it also returns a "Success" or "Fail" message back to the K2 workflow through the datafield called "ExternalAppResponse" using JSON.
/// </summary>
/// <param name="stepSerialNumber">Serial number of the K2 workflow step(SmartObject Event) that is waiting on this external application to finish. Use this in the
/// URL path for this REST endpoint.</param>
/// <param name="appResponse">Pass in a response with this parameter to send back to K2 using a workflow defined variable named "ExternalAppResponse". Values will either be "Success" or "Fail"</param>
/// <param name="baseURL">Base URL for the REST endpoint. Build the full REST endpoint URI with either V1 or Preview version of the REST serverEvents endpoints.</param>
///
protected async void FinishK2StepbyREST(string stepSerialNumber, string appResponse, string baseURL) {
HttpResponseMessage rm;
// Build the JSON string to send back datafields with data, if necessary. In this example, we're passing back a response from this external application of "Success" or "Fail"
// through a datafield called "ExternalAppResponse", which corresponds to a variable defined in the running instance of the K2 workflow.
string userDefinedFields = "{\"dataFields\": { \"ExternalAppResponse\": \"" + appResponse + "\"}}";
// Example: "https://[K2 SERVER DOMAIN]/api/workflow/preview/serverEvents/" + stepSerialNumber + "/finish";
string requestUri = baseURL + stepSerialNumber + "/finish";
System.Net.Http.StringContent httpContent = new StringContent(userDefinedFields, Encoding.UTF8, "application/json");
try {
rm = await k2CloudClient.PostAsync(requestUri, httpContent);
if (rm.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
// Unauthorized user account making the event Finish call.
// TODO: Ensure external application is running under an account with access to complete the workflow step in K2.
} else if (rm.StatusCode == System.Net.HttpStatusCode.BadRequest) {
// Could be badly formed JSON string with datafield sent back to K2.
// TODO: Ensure datafields sent back, exist as variables in the K2 Workflow.
}
} catch (Exception ex) {
// handle errors accordingly
}
}
You can use the Workflow Client API's ServerItem object to finish the waiting SmartObject event. (In this example, we also return a value back to the K2 workflow through a workflow variable. In this example, the external system returns either Success or Fail message back to the workflow. into a variable called ExternalAppResponse.)
- The method parameter stepSerialNumber is the serial number of the K2 workflow step waiting on the external application.
- The method parameter appResponse is used to send a response back to the K2 workflow using a variable named ExternalAppResponse. The values is either Success or Fail.
- The method parameter host is a string representing the connection string to connect to the K2 workflow server on port 5252.
/// This method uses the K2 Client api with a ServerItem object to finish an Asynchronous SmartObject event.
/// NOTE: it also returns a "Success" or "Fail" message back to the K2 workflow through the datafield called "ExternalAppResponse".
/// </summary>
/// <param name="stepSerialNumber">Serial number of the K2 step waiting on this external application to send complete notice. This value can come into your external
/// application by polling a SmartObject datasource, or whatever method you use to pull in external data.
/// </param>
/// <param name="appResponse">Pass in a response with this parameter to send back to K2 using a workflow defined variable named "ExternalAppResponse". Values will either be "Success" or "Fail"</param>
/// <remarks>TODO: Ensure external application is running under an account with access to complete the workflow step in K2.</remarks>
private void FinishK2StepbyAPI(string stepSerialNumber, string appResponse, string host) {
using(SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
try {
K2Conn.Open(host);
// Use the ServerItem object to open the SmartObject step that is waiting in the workflow. Do this by passing in the step serial number.
ServerItem svrItem = K2Conn.OpenServerItem(stepSerialNumber);
// Pass datafield values back to K2, if necessary. In this example, we're passing back a response from this external application of "Success" or "Fail"
// through a datafield called "ExternalAppResponse", which corresponds to a variable defined in the running instance of the K2 workflow.
svrItem.ProcessInstance.DataFields["ExternalAppResponse"].Value = appResponse;
// Finish the server item to tell the workflow to continue
svrItem.Finish();
} catch (Exception ex) {
// Handle errors accordingly.
}
}
}
In this step you test the solution by manually starting an instance of the Sample External System Workflow. Keeping with the sales order scenario, an external app represents the external system and deal with the order confirmation. The workflow starts and sends order information to the external system through the Wait On External System SmartObject step. In this example it sends the Step Serial number to the external system and the Status property gets set as Waiting. The SmartObject waits for the external system to send a message back, identifying the workflow with the Step Serial number, and the workflow continues. A decision rule then send the workflow either in the Success or Fail path based on the response from the external system.
Use the View Flow to track the progress of the workflow or use a view to track how the Status property changes on the SmartObject.
In this test you start the workflow manually and use the instance view flow to track the progress.
- Using K2 Management, manually start an instance of Sample External System Workflow.
- From K2 Management, select the Reports tab. Scroll down to the All Instances section, select the workflow and click the View Flow link.
- At this stage, the workflow is active and currently at the Wait On External System step. The Step Serial Number was sent to the external system and the Status property is set as Waiting.
- To illustrate the external process, open the Wait for External System - External App by running the ExternalSystemSample.exe. This simulates the external order confirmation process, but is a simple app that you can download as proof of concept. Notice the order is currently in a Waiting state.
- To simulate and finalize the external event, select the order confirmation and set the response to Success. Click Post REST. This response is sent back to the workflow.
- Refresh the external app to show the Processed - Success status.
- Refresh the View Flow. At this stage, the Wait On External System SmartObject step in the workflow received the Processed - Success status message from the external system and the step went from waiting to moving on to the next step. The value passed back from the external system into the variable was evaluated by the custom decision rule and the Success path was followed.
In this test, you generate a list view on the SmartObject and track how the process updates.
- From the K2 Designer locate All Items > K2 Documentation and right click and select Sample External System Async category. From the menu, select New Category.
- Name this category Views. Click OK.
- From the K2 Designer right click External System SmartObject and select Generate Views.
- On the Generate Options page, make sure that the list view is generated in the correct category. In this example, it is generated in the Views category. Check the List check box and then click OK.
- From K2 Management manually start an instance of Sample External System Workflow.
- From the Views category select the External System SmartObject List view and click Run.
- With the workflow started and active, the status is Waiting.
- To illustrate the external process, open the Wait for External System - External App by running the ExternalSystemSample.exe. This simulates the external order confirmation process, but is a simple app that you can download as proof of concept. Notice the order is currently in a Waiting state.
- To simulate and finalize the external event, select the order confirmation and set the response to Fail. Click Post REST. This response is sent back to the workflow.
- Refresh the external app to show the Processed - Fail status.
- Refresh the External System SmartObject List view. Notice the Status property updated and shows Processed - Fail. The step waited for a reply from the external system (in this case Fail) and then updated the SmartObject Status property accordingly. The workflow continued and finished successfully.