Defining Workflows
Exploring the Workflow Sample
[Back] [Next]
   
Server:docs2
Instance:LATEST
User:UnknownUser
 
-
Search:    

This appendix presents an sample that you can find in the package Demo.Workflow in the ENSDEMO namespace. So that you can more easily work with this sample, the appendix also includes some setup information and suggestions on points of interest. This appendix includes the following sections:

Overview of the Sample
The Demo.Workflow sample includes a business process called Demo.Workflow.HelpDesk. This accepts an incoming request that contains the basic information required for a problem report; that is, the name of the sender and a description of the problem. On receiving this request for action, HelpDesk begins a sequence of actions that continues until one of these actions resolves the problem.
HelpDesk first sends the problem report, as a task, to the development group. When a member of this group reports that the problem was solved, HelpDesk adds a note to the problem report and sends it, as a task, to the testing group. When a member of this group reports that the repairs were satisfactory, HelpDesk sends a final response to its caller, with a flag indicating that the reported problem was resolved.
Setup Tasks
To set up and work with this sample, do the following:
  1. Create several users as described in Users in the Caché Security Administration Guide.
  2. Configure each of these users as a workflow user, as described in Managing Workflow Roles, Users, and Tasks in Managing Ensemble.
  3. In the ENSDEMO namespace, start the production Demo.Workflow.Production.
    When you do so, Ensemble creates two workflow roles: Demo-Development and Demo-Testing. (It creates these roles because the Auto Create Role setting is enabled for the two workflow operations in the production.)
  4. Assign the workflow users to these workflow roles, as described in Managing Workflow Roles, Users, and Tasks in Managing Ensemble.
    Some users can be in both roles.
  5. Use the [Ensemble] > [Testing Service] page to send a few messages to HelpDesk:
    1. Click Ensemble, then click Testing, then click Business Hosts.
    2. For Target Name, click HelpDesk.
    3. Click Test.
    4. Type suitable values into the ReportedBy and Problem fields.
    Send several messages to make the scenario interesting.
  6. Log into the DeepSee User Portal as each of the users and use the Workflow Inbox to manage the tasks.
    First log in as a user in the Demo-Development role and mark some tasks as complete; this generates additional testing tasks. Then log in as a user in the Demo-Testing role and mark the testing tasks complete.
    Tip:
    You might need to configure the /csp/ensdemo web application so that it accepts password authentication but does not accept unauthenticated access. For details, see in Applications in the Caché Security Administration Guide.
Sample Request Message
The following request message class defines the request message that comes into the HelpDesk sample business process. It represents a technical problem submitted by a customer. The request message class definition is as follows:
Class Demo.Workflow.ProblemReport
{
/// Name of customer reporting the problem.
Property ReportedBy As %String(MAXLEN = 60);

/// Description of the problem.
Property Problem As %String(MAXLEN = 200);
}
Sample Business Process Class
On receiving a Demo.Workflow.ProblemReport request message, the sample BPL business process Demo.Workflow.HelpDesk begins a sequence of actions that continues until one of these actions resolves the problem.
The HelpDesk business process consists of a while loop, during which a problem report is sent, first to the development group for a problem to be fixed, and next to the testing group for the fix to be tested. Upon completion of this sequence, the while condition “Resolved” is satisfied, and the business process ends, returning its final response to its caller.
When viewed in the Business Process Designer, the HelpDesk business process looks like this:
The top area of the expanded while loop appears as follows:
The bottom section is as follows:
The code within the while loop makes two calls to workflow, using the built-in task request and task response classes for each call. The difference between the two <call> elements is easier to see in the BPL source code:
Class Demo.Workflow.HelpDesk Extends Ens.BusinessProcessBPL 
{

XData BPL
{
<process request='Demo.Workflow.ProblemReport'
         response='Ens.Response' >
  <context>
    <property name='Resolved' type='%Boolean' initialexpression='0' />
    <property name='DevelopmentAction' type='%String' />
    <property name='TestingAction' type='%String' />
  </context>

  <sequence>
    <while name='while'
           condition='context.Resolved=0' >
      <annotation>
        Work on this problem until it is resolved.
        (Click on the loop icon to see details of this while loop.)
      </annotation>

      <call name='Notify Development'
            target='Demo-Development'
            async='1' >
        <annotation>
          Send the problem report to Development for review.
        </annotation>
        <request type='EnsLib.Workflow.TaskRequest' >
          <assign property='callrequest.%Actions'
                  value='"Corrected,Ignored"'
                  action='set' />
          <assign property='callrequest.%Subject'
                  value='"Problem reported by "_request.ReportedBy'
                  action='set' />
          <assign property='callrequest.%Message'
                  value='request.Problem'
                  action='set' />
          <assign property='callrequest.%FormFields'
                  value='"Comments"'
                  action='set' />
        </request>
        <response type='EnsLib.Workflow.TaskResponse' >
          <assign property='context.DevelopmentAction'
                  value='callresponse.%Action'
                  action='set' />
        </response>
      </call>

      <sync name='WaitForDevelopment' calls='Notify Development' type='all' />

      <if name='Fixed?' condition='context.DevelopmentAction="Corrected"' >
        <annotation>
          If Development fixed the problem, test it.
        </annotation>

        <true>
          <call name='Notify Testing'
                target='Demo-Testing'
                async='1' >
            <annotation>
              Send the problem to Testing for confirmation.
            </annotation>
            <request type='EnsLib.Workflow.TaskRequest' >
              <assign property='callrequest.%Actions'
                      value='"Corrected,Retest"'
                      action='set' />
              <assign property='callrequest.%Subject'
                      value='"Test this problem from "_request.ReportedBy'
                      action='set' />
              <assign property='callrequest.%Message'
                      value='request.Problem'
                      action='set' />
            </request>
            <response type='EnsLib.Workflow.TaskResponse' >
              <assign property='context.TestingAction'
                      value='callresponse.%Action'
                      action='set' />
            </response>
          </call>

          <sync name='WaitForTesting' calls='Notify Testing' type='all' />

          <if name='Corrected?' condition='context.TestingAction="Corrected"' >
            <annotation>Has the problem been corrected?</annotation>
            <true>
              <assign name='Resolved'
                      property='context.Resolved'
                      value='1'
                      action='set' />
            </true>
          </if>
        </true>

        <false>
          <assign name='Not a problem'
                  property='context.Resolved'
                  value='1'
                  action='set' />
        </false>

      </if>
    </while>
  </sequence>
</process>
}
}
Sample Control Flow
When the production is running, the BPL business process example Demo.Workflow.HelpDesk works as follows. Try comparing the steps in this control flow with the corresponding statements in the BPL source code, shown in the previous section:
  1. A message of type Demo.Workflow.ProblemReport tells the business process who reported the problem, and provides a brief text string to describes the problem. The values for both these properties are provided by the business host that invokes this business process.
  2. In preparing the <call> to the Demo-Development workflow operation, the Demo.Workflow.HelpDesk business process uses the incoming request properties ReportedBy and Problem to fill in the task request fields %Subject and %Message, respectively. Two other built-in task properties come into play as well: The call creates a list of possible user actions by assigning the %Actions field a value of Corrected,Ignored. The call also prepares a form field called Comments in which the person reviewing this task can enter data.
  3. The business process makes the <call> to Demo-Development asynchronously, and provides a <sync> element to catch the task response.
  4. The Workflow Engine associates the task with each workflow user in the Demo-Development workflow role.
  5. One of the workflow users accepts the task. The Workflow Engine assigns the task to that user.
  6. The assigned user edits the Comments field and clicks one of the actions Corrected or Ignored.
  7. The task response returns. Its %Action field contains the value of the user action that completed the task (Corrected or Ignored). The business process saves this value into a execution context property called DevelopmentAction.
  8. The business process uses an <if> element to test the DevelopmentAction value. The results are as follows:
  9. In preparing the <call> to the Demo-Testing workflow operation, the business process uses the original, incoming request properties ReportedBy and Problem to fill in the task request fields %Subject and %Message, respectively. However, unlike the previous <call>, the <call> to Demo-Testing has no form fields defined. Also, the list of possible user actions is different: %Actions is different: This <call> assigns the %Actions field a value of Corrected,Retest.
  10. The business process makes the <call> to Demo-Testing asynchronously, and provides a <sync> element to catch the task response.
  11. The Workflow Engine associates the task with each workflow user in the Demo-Testing workflow role.
  12. One of the workflow users accepts the task. The Workflow Engine assigns the task to that user.
  13. The assigned user clicks either Corrected or Retest.
  14. The task response returns. Its %Action field contains the value of the user action that completed the task (Corrected or Retest). The business process saves this value into a execution context property called TestingAction.
  15. The business process uses an <if> element to test the TestingAction value. The results are as follows:
Dashboards and Metrics
To see a business metric and dashboard working together to display workflow role statistics, use Studio to view the sample classes Demo.Workflow.WFMetric and Demo.Workflow.Dashboard in the ENSDEMO namespace.
The following sample code from the business metric class Demo.Workflow.WFMetric calls three of the available statistical methods and assigns their return values to metric properties. The next appendix describes the available methods.
/// Sample business metric class for Workflow demo
Class Demo.Workflow.WFMetric Extends Ens.BusinessMetric
{

/// Active Tasks
Property ActiveTasks As Ens.DataType.Metric(AUTOHISTORY = 10, RANGELOWER = 0,
                                     RANGEUPPER = 50, UNITS = "Tasks")
                                     [ MultiDimensional ];

/// Active Load
Property Load As Ens.DataType.Metric(AUTOHISTORY = 10, RANGELOWER = 0,
                                     RANGEUPPER = 100, THRESHOLDUPPER = 90,
                                     UNITS = "%") [ MultiDimensional ];

/// Completed Tasks (since previous day)
Property CompletedTasks As Ens.DataType.Metric(AUTOHISTORY = 10, RANGELOWER = 0,
                                     RANGEUPPER = 100, UNITS = "Tasks")
                                     [ MultiDimensional ];

/// Calculate and update the set of metrics for this class
Method OnCalculateMetrics() As %Status
{
  // set the values of our metrics
  // %Instance is the current instance (RoleName in this case)
  Set tRole = ..%Instance

  Set ..ActiveTasks = ##class(EnsLib.Workflow.Engine).BamActiveTasks(tRole)
  Set ..Load = ##class(EnsLib.Workflow.Engine).BamActiveLoad(tRole)

  // Get task since start of previous day
  Set tStart = $ZDT($H-1,3)

  Set ..CompletedTasks =
      ##class(EnsLib.Workflow.Engine).BamCompletedTasks(tRole,tStart)

  Quit $$$OK
}

/// Set of instances for this metric class
/// There is one instance for every defined role.
Query MetricInstances() As %SQLQuery
{
  SELECT Name FROM EnsLib_Workflow.RoleDefinition
}

}
For information about the ObjectScript functions $ZDT ($ZDATETIME) and $H ($HOROLOG) used here , see the chapter Caché ObjectScript Functions in the Caché ObjectScript Reference.