An example of parallel activities

The logic of the Sale business transaction is changed so that an order can include multiple items, each potentially requiring delivery to a separate location. Each delivery request (activity) can run in parallel, but the customer is not invoiced until all of the items have been delivered.

Data flow

Figure 17 shows data flows in the Sale example application when parallel activities are included.

Figure 17. Data flow for parallel activities. (The root activity is not shown.) Changes from the basic Sale example described in The Sale example application are shown in bold.
 The picture shows the data flows described in the list below. A rectangle represents the Sale business transaction. The rectangle contains several smaller rectangles, representing the Order, Delivery, Invoice, and Payment child activities. There are several instances of the Delivery activity. Another rectangle, outside the Sale transaction, represents the Menu transaction. Input and output data flows are represented by arrows.   The Menu transaction collects input from the user. The output from the Menu transaction becomes the input to the Order activity. The Order activity collects further input from the user. The output from the Order activity becomes the input to multiple Delivery activities. The output from the Delivery activities becomes the input to the Invoice activity. The output from the Invoice activity becomes the input to the Payment activity.

The root activity

Figure 18 shows, in COBOL pseudocode, the Sale root activity with modifications for parallel activities. CHECK ACTIVITY commands have also been added, to check the response from each child activity (and to delete its completion event). The changes are in bold text.

Figure 18. The SAL002 root activity program, with modifications for parallel activities highlighted
Identification Division.
Program-id. SAL002.
Environment Division.
Data Division.
Working-Storage Section.
01  Switches.
    05  No-More-Events               pic x value space.
        88  No-More-Events                 value 'y'.
01  Switch-Off                       Pic x value 'n'.
01  RC                               pic s9(8) comp.
01  Process-Name                     pic x(36).
01  Event-Name                       pic x(16).
    88  DFH-Initial                  value 'DFHINITIAL'.
    88  Delivery-Complete            value 'Delivry-Complete'.
    88  Invoice-Complete             value 'Invoice-Complete'.
    88  Payment-Complete             value 'Payment-Complete'.
01  Sale-Container                   pic x(16) value 'Sale'.
01  Order-Container                  pic x(16) value 'Order'.
01  Order-Buffer.
    05  Order-Count                  Pic 9(2).
    05  Order-Item occurs 1 to 20 times
        Depending on Order-Count     Pic X(10).
01  Delivery-Container               pic x(16) value 'Delivery'.
01  Delivery-Buffer.
    05  Delivery-Count               pic 9(2).
    05  Delivery-Item occurs 1 to 20 times
        Depending on Delivery-Count  pic x(30).
01  Invoice-Container                pic x(16) value 'Invoice'.
01  Invoice-Buffer                   Pic x(..).
01  Work-Activity.
    05  Work-Name                    Pic x(8) value 'Delivery'.
    05  Filler                       pic x(6) value '-Item-'.
    05  Work-Count                   pic 9(2) value zero.
01  Work-Event.
    05  Event-Name                   pic x(8) value 'Del-Comp'.
    05  Filler                       pic x(6) value '-Item-'.
    05  Event-Count                  pic x(2) value zero.
Linkage Section.
01  DFHEIBLK.
    .
Procedure Division.
Begin-Process.
      .
    EXEC CICS RETRIEVE REATTACH EVENT(Event-Name)
              RESP(RC) END-EXEC
      .
    If RC NOT = DFHRESP(NORMAL)
      .
    End-If.
        .
    Evaluate True
      When DFH-Initial
        Perform Initial-Activity
        Perform Order-Activity
        Perform Order-Response
        Perform Delivery-Activity
      When Delivery-Complete
        Perform Delivery-Response
        Perform Invoice-Activity
      When Invoice-Complete
        Perform Invoice-Response
        Perform Payment-Activity
      When Payment-Complete
        Perform Payment-Response
        Perform End-Process
      When Other
        .
    End Evaluate.
 
    EXEC CICS RETURN END-EXEC
        .
Initial-Activity.
    .
    EXEC CICS ASSIGN PROCESS(Process-Name)
              RESP(data-area) RESP2(data-area) END-EXEC
    .
Order-Activity.
    .
    EXEC CICS DEFINE ACTIVITY('Order')
                 TRANSID('SORD')
                 PROGRAM('ORD001')
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER(Sale-Container)
                 ACTIVITY('Order') FROM(Process-Name)
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS LINK ACTIVITY('Order')
              RESP(data-area) RESP2(data-area) END-EXEC
    .
Order-Response.
    .
    EXEC CICS CHECK ACTIVITY('Order') COMPSTATUS(status)
             RESP(RC) RESP2(data-area) END-EXEC
    .
    If RC NOT = DFHRESP(NORMAL)
        .
    End-If.
    .
    If status NOT = DFHVALUE(NORMAL)
        .
    End-If.
    .
Delivery-Activity.
    .
    EXEC CICS GET CONTAINER(Order-Container)
                 ACTIVITY('Order') INTO(Order-Buffer)
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DEFINE COMPOSITE EVENT('Delivry-Complete') AND
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    Perform Delivery-Work varying Work-Count from 1 by 1
      until Work-Count greater than Order-Count.
    .
Delivery-Work.
    .
    Move Work-Count to Event-Count
    .
    EXEC CICS DEFINE ACTIVITY(Work-Activity)
                 TRANSID('SDEL')
                 PROGRAM('DEL001')
                 EVENT(Work-Event)
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS ADD SUBEVENT(Work-Event) EVENT('Delivry-Complete')
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER(Order-Container)
                 ACTIVITY(Work-Activity) FROM(Order-Item(Work-Count))
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACTIVITY(Work-Activity)
                 ASYNCHRONOUS
              RESP(data-area) RESP2(data-area) END-EXEC
    .
Delivery-Response.
    .
    Move zeros to Delivery-Count
    Move Switch-Off to No-More-Events
    .
    Perform until No-More-Events
    EXEC CICS RETRIEVE SUBEVENT(Work-Event) EVENT('Delivry-Complete')
              RESP(data-area) RESP2(data-area) END-EXEC
 
    If RC NOT = DFHRESP(NORMAL)
       .
       If RC = DFHRESP(END)
          Set No-More-Events to TRUE
          EXEC CICS DELETE EVENT('Delivry-Complete') 
       Else
          .
       End-If
    Else
       Move Event-Count to Work-Count
       Add 1 to Delivery-Count
       .
       EXEC CICS CHECK ACTIVITY(Work-Activity) COMPSTATUS(status) 
                RESP(RC) RESP2(data-area) END-EXEC 
       .
       If RC NOT = DFHRESP(NORMAL)
           .
       End-If.
       .
       If status NOT = DFHVALUE(NORMAL)
           .
       End-If.
       .
       EXEC CICS GET CONTAINER(Delivery-Container)
                     ACTIVITY(Work-Activity)
                     INTO(Delivery-Item(Work-Count))
                 RESP(data-area) RESP2(data-area) END-EXEC
    .
    End-If
    End-Perform
    .
Invoice-Activity.
    .
    EXEC CICS DEFINE ACTIVITY('Invoice')
                 TRANSID('SINV')
                 EVENT('Invoice-Complete')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER(Delivery-Container)
                 ACTIVITY('Invoice') FROM(Delivery-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACTIVITY('Invoice')
                 ASYNCHRONOUS
             RESP(data-area) RESP2(data-area) END-EXEC
    .
Invoice-Response.
    .
    EXEC CICS CHECK ACTIVITY('Invoice') COMPSTATUS(status)
             RESP(RC) RESP2(data-area) END-EXEC
    .
    If RC NOT = DFHRESP(NORMAL)
        .
    End-If.
    .
    If status NOT = DFHVALUE(NORMAL)
        .
    End-If.
    .
Payment-Activity.
    .
    EXEC CICS DEFINE ACTIVITY('Payment')
                 TRANSID('SPAY')
                 EVENT('Payment-Complete')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS GET CONTAINER(Invoice-Container)
                 ACTIVITY('Invoice') INTO(Invoice-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER(Invoice-Container)
                 ACTIVITY('Payment') FROM(Invoice-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACTIVITY('Payment')
                 ASYNCHRONOUS
             RESP(data-area) RESP2(data-area) END-EXEC
    .
Payment-Response.
    .
    EXEC CICS CHECK ACTIVITY('Payment') COMPSTATUS(status)
             RESP(RC) RESP2(data-area) END-EXEC
    .
    If RC NOT = DFHRESP(NORMAL)
        .
    End-If.
    .
    If status NOT = DFHVALUE(NORMAL)
        .
    End-If.
    .
End-Process.
    .
    EXEC CICS RETURN ENDACTIVITY
             RESP(data-area) RESP2(data-area) END-EXEC
End Program.

The output from the Order activity (retrieved into the variable Order-Buffer) is now an array of order items. There can be between 1 and 20 items in an order. Having first defined a composite event (Delivry-Complete), SAL002 requests a delivery activity to be run for each item ordered:

    EXEC CICS DEFINE COMPOSITE EVENT('Delivry-Complete') AND
              RESP(data-area) RESP2(data-area) END-EXEC
    .
    Perform Delivery-Work varying Work-Count from 1 by 1
      until Work-Count greater than Order-Count.

All the delivery activities will run in parallel. The following set of requests are made for each order item:

Delivery-Work.
    .
    Move Work-Count to Event-Count
    .
    EXEC CICS DEFINE ACTIVITY(Work-Activity)
                 TRANSID('SDEL')
                 PROGRAM('DEL001')
                 EVENT(Work-Event)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS ADD SUBEVENT(Work-Event) EVENT('Delivry-Complete')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER(Order-Container)
                 ACTIVITY(Work-Activity) FROM(Order-Item(Work-Count))
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACTIVITY(Work-Activity)
                 ASYNCHRONOUS
             RESP(data-area) RESP2(data-area) END-EXEC

Note that:

Before the Invoice activity is run, the output from each of the delivery activities is accumulated into a Delivery-Item array:

Delivery-Response.
    .
    Move zeros to Delivery-Count
    Move Switch-Off to No-More-Events
    .
    Perform until No-More-Events
    EXEC CICS RETRIEVE SUBEVENT(Work-Event) EVENT('Delivry-Complete')
              RESP(data-area) RESP2(data-area) END-EXEC
 
    If RC NOT = DFHRESP(NORMAL)
       .
       If RC = DFHRESP(END)
          Set No-More-Events to TRUE
          EXEC CICS DELETE EVENT('Delivry-Complete')
       Else
           .
       End-If
    Else
       Move Event-Count to Work-Count
       Add 1 to Delivery-Count
       .
       EXEC CICS CHECK ACTIVITY(Work-Activity) COMPSTATUS(status)
                RESP(RC) RESP2(data-area) END-EXEC
       .
       If RC NOT = DFHRESP(NORMAL)
           .
       End-If.
       .
       If status NOT = DFHVALUE(NORMAL)
           .
       End-If.
       .
       EXEC CICS GET CONTAINER(Delivery-Container)
                     ACTIVITY(Work-Activity)
                     INTO(Delivery-Item(Work-Count))
                 RESP(data-area) RESP2(data-area) END-EXEC
    .
    End-If
    End-Perform

The contents of the Delivery-Item array are placed in the input data-container of the Invoice activity.

Note that:

Related concepts
Using the BTS API to write business applications
The Sale example application
Related tasks
Dealing with BTS errors and response codes
Interacting with BTS processes and activities
Compensation in BTS
Reusing existing 3270 applications in BTS
Related reference
Overview of BTS API commands
BTS application programming commands
[[ Contents Previous Page | Next Page Index ]]