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

-
User data (an account number) collected after the user selects the
Salemenu 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
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.
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
- 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.
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.
- 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.