Example of running parallel BTS activities

Many business transactions include activities that can run in parallel with one another. To illustrate parallel activities, the following example extends the Sale business transaction to support multiple delivery 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 the items have been delivered.

Data flow

Follow this example to see how data flows in the Sale example application when parallel activities are included. The root activity is not shown. Changes from the basic Sale example described in The Sale example application are shown in bold.
Figure 1. Data flow for parallel activities
The picture shows the data flow of user input data and output data. 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.
  • User data (an account number) collected after the user selects the Sale menu option is used as input to the Order activity.
  • User data collected by the Order activity is used as input to multiple Delivery activities.
  • The output data produced by the Delivery activities is used as input to the Invoice activity.
  • The output produced by the Invoice activity is used as input to the Payment activity.

Root activity

Figure 2 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 2. The SAL002 root activity program, with modifications for parallel activities highlighted (Part 1)

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..
Figure 3. The SAL002 root activity program, with modifications for parallel activities highlighted (Part 2)

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.
Figure 4. The SAL002 root activity program, with modifications for parallel activities highlighted (Part 3)

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

Figure 5. The SAL002 root activity program, with modifications for parallel activities highlighted (Part 4)

 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.
.
Figure 6. The SAL002 root activity program, with modifications for parallel activities highlighted (Part 5)

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 1 - 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 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:
  • The delivery activity for each order item is given a unique name ( Delivery-Item-n —the value of Work-Activity —where n is the 1-20 item number).
  • Each delivery activity is provided with an input data-container named Order , which contains one of the order items from the Order-Buffer array.
  • The completion event for each delivery activity is given a unique name ( Del-Comp-Item-n , the value of Work-Event ). The ADD SUBEVENT command is used to add the completion event for each delivery activity to the composite event Delivry-Complete.

    The completion of an individual delivery activity does not cause SAL002 to be reattached—because the completion events of the delivery activities have been specified as subevents of the composite event Delivry-Complete . Instead, SAL002 is reattached when Delivry-Complete fires. Because Delivry-Complete uses the AND Boolean operator, it fires when all the completion events of the individual delivery activities have fired.

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:
  • When SAL002 is reattached due to the firing of the Delivry-Complete composite event, it uses a succession of EXEC CICS RETRIEVE SUBEVENT commands to retrieve, in turn, each subevent on the subevent queue of the composite event - that is, each subevent whose firing was instrumental in the firing of the composite event. These subevents are the completion events for each of the delivery activities. The number of each subevent (contained in the Event-Count field of Work-Event ) is used to identify the particular delivery activity for which the subevent is the completion event.
  • When all the subevents have been retrieved, SAL002 deletes the composite event Delivry-Complete . This deletion is not strictly necessary, because user-defined events, other than activity completion events, are automatically deleted by CICS when a RETURN ENDACTIVITY command is issued.

    Deleting a composite event does not delete any associated subevents. In this example, the subevents are the completion events for child activities. The completion event for a child activity is deleted automatically when, as here, an EXEC CICS CHECK ACTIVITY command is issued by the parent after the child has completed. The CHECK ACTIVITY command is described in Dealing with BTS errors and response codes.

    It is an error for an activity to issue an EXEC CICS RETURN ENDACTIVITY command while there are still activity completion events in its event pool.