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.
Figure 17 shows data flows in the Sale example application when parallel activities are included.
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.
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:
The completion of an individual delivery activity will not cause SAL002 to be reattached--because the delivery activities’ completion events have been specified as sub-events of the composite event Delivry-Complete. Instead, SAL002 will be reattached when Delivry-Complete fires. Because Delivry-Complete uses the AND Boolean operator, it will fire 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:
Note that deleting a composite event does not delete any associated sub-events. In the example in this section, the sub-events 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.