Other examples (Scripting)
This section provides script editing examples.
Modify APPC script data – scenario 1
The following script uses the recommended method for modifying APPC script data — using the <REPLACE> tag inside the <OUTBOUND> section to replace <CMSEND> <CONTENT> data. <REPLACE> uses an offset method to indicate where to start replacing.
Script for Modifying Script Data Using the <REPLACE> Tag
<ADDCALL>COMPAPPC appc_expected, appc_actual, appc_expected_length, appc_actual_length
target_domain = "H01AC079"
source_domain = "H01APPCP"
"EXECIO * DISKR MESSAGES (STEM msg_in. FINIS"
say "Message is:" msg_in.port "length:" length(msg_in.port)
<DETAIL COMBINED='*'>
<TIME>2006/11/02_11:22:12.380705
<PIU>
<CONTENT> ï00000001 ßÇ-
‡… l,Ã Ò ^^&úgiig¹ ³ ßH01AC079 #INTERÌ.§©iW¾ÌêUSCWXN01.H01AC079 ßH01AC074-”Áí
øïhDUSCWXN01.CWXCDRM3USCWXN01.H01AC079ËÍß
<TIME>2006/11/02_11:22:12.385948
<PIU>
<CONTENT> i00000002 -ßLJ… ŽõÃ Ò ^^&ú Ãiià ¹ ³ #INTERÌ0.§©iW¾Ì USCWXN01.H01AC074
-”Áí øïhDUSCWXN01.CWXCDRM
<TIME>2006/11/02_11:22:12.411075
<PIU>
<CONTENT> |00000003 ßÇ- …næ ü J H3S ÓUSCWXN01.CW010001.§©dì« ê- AA1 üRIGHT SAID FRED
<TIME>2006/11/02_11:22:12.411075
<CMALLC TPNAME=H3S SENDER=USCWXN01.³³source_domain,
RECEIVER=USCWXN01.³³target_domain,
LOGMODE=#INTER TYPE=MAPPED SYNCLVL=NONE SECURITY=NONE
STIME='2006/11/02_11:22:12.411075'
FTIME='2006/11/02_11:22:12.725288
CONVCORR='-AA1' LUWNAME=USCWXN01.CW010001 LUWINST=,
'4B9B218446B8'X LUWSEQ='0001'X>
say "Receiver is:" receiver "sender is:" sender
send_data = "RIGHT SID CHRIS"
say "Port number is:" port
dat_len = X2C(length(msg_in.port))
dat_pos = 3
<OUTBOUND>
<TIME>2006/11/02_11:22:12.411075
<REPLACE FIELD=(dat_pos,msg_in.port) TYPE=ONE>
<CMSEND DATATYPE=APPLDATA>
<CONTENT> Ï 00000004RIGHT SID CHRIS
<TIME>2006/11/02_11:22:12.411075
<CMPTR TYPE=FLUSH>
</OUTBOUND>
<INBOUND>
<TIME>2006/11/02_11:22:12.725288
<PIU>
<CONTENT> Í00000005 -ßÇ j üDERF DIAS THGIR
<TIME>2006/11/02_11:22:12.725288
<CMSEND DATATYPE=APPLDATA>
<CONTENT> Ï 00000006DERF DIAS THGIR
<TIME>2006/11/02_11:22:12.725288
<CMDEAL TYPE=FLUSH LOGDATA=NO>
</INBOUND>
Modify APPC script data – scenario 2
This is an alternative method of modifying APPC script data.
Alternative Method for Modifying APPC Script Data
<ADDCALL>COMPAPPC appc_expected, appc_actual, appc_expected_length, appc_actual_length
parse source op_sys how_called scr_name rest
address HSCMDS "ALLOC F(DETAILS) DA(USR2503.TSTEAM.DETAIL("scr_name")",
" SHR REUS"
"EXECIO * DISKR DETAILS (STEM data_in. FINIS"
address HSCMDS "FREE F(DETAILS)"
parse var data_in.2 len_type "00000002" rest
"EXECIO * DISKR MESSAGES (STEM msg_in. FINIS"
say "Message is:" msg_in.port "length:" length(msg_in.port)
out_data = msg_in.port
data_in.2 = '00'X³³D2C(length(out_data)+12)³³substr(len_type,3,2)³³,
"00000002"³³out_data
say "length:" C2D(substr(data_in.2,1,2))
new_mem = "H3C1NW"³³RIGHT(port,2,'0')
say "New Member:" new_mem
address HSCMDS "ALLOC F("new_mem") DA(USR2503.TSTEAM.DETAIL("new_mem")) OLD
REUS"
"EXECIO" data_in.0 "DISKW" new_mem "(STEM data_in. FINIS"
address HSCMDS "FREE F("new_mem")"
detail_mem = "H3C10000"
<DETAIL COMBINED='DETAIL('³³new_mem³³')'>
<TIME>2006/11/02_11:25:54.424879
<PIU LABEL=00000001>
<TIME>2006/11/02_11:25:54.424879
<CMALLC TPNAME=H3S SENDER=USCWXN01.H01APPCP RECEIVER=USCWXN01.H01AC079
LOGMODE=#INTER TYPE=MAPPED SYNCLVL=NONE SECURITY=NONE
STIME='2006/11/02_11:25:54.424879' FTIME='2006/11/02_11:25:54.435640'
CONVCORR='-AA1' LUWNAME=USCWXN01.CW010001 LUWINST=,
'4B9BBC105B62'X LUWSEQ='0001'X>
SAY "Receiver is:" RECEIVER "Sender is:" SENDER "Port:" PORT
<OUTBOUND>
<TIME>2006/11/02_11:25:54.424879
<CMSEND DATATYPE=APPLDATA LABEL=00000002>
<TIME>2006/11/02_11:25:54.424879
<CMPTR TYPE=FLUSH>
</OUTBOUND>
<INBOUND>
<TIME>2006/11/02_11:25:54.435640
<PIU LABEL=00000003>
<TIME>2006/11/02_11:25:54.435640
<CMSEND DATATYPE=APPLDATA LABEL=00000004>
<TIME>2006/11/02_11:25:54.435640
<CMDEAL TYPE=FLUSH LOGDATA=NO>
</INBOUND>
To explain the code, we will look at individual pieces.
- Retrieve the user data from the associated DETAIL member:
parse source op_sys how_called scr_name rest
address HSCMDS “ALLOC F(DETAILS) DA(USR2503.TSTEAM.DETAIL(“scr_name”)”,
“SHR REUS”
“EXECIO * DISKR DETAILS (STEM data_in.FINIS”
address HSCMDS “FREE F(DETAILS)” - Determine which user <CONTENT> data record to modify using the attached LABEL and extract record type information:
parse var data_in.2 len_type “00000002” rest - Retrieve new data from the MESSAGE file and use the replay PORT number (provided by Performance Test) to select the replacement record for this user:
“EXECIO * DISKR MESSAGES (STEM msg_in.FINIS”
out_data = msg_in.port - Build the replacement user <CONTENT> data record:
data_in.2 = ‘OO’X||D2C(length(out_data)+12)||substr(len_type,3,2)||,
“00000002”||out_data - Build member name for replacement DETAIL member that contains the replacement user <CONTENT> record, again using the PORT number for uniqueness:
new_mem=”H3C1NW”||RIGHT(port,2,’0’) - Create new DETAIL member:
address HSCMDS “ALLOC(F(“new_mem”) DA(USR2503.TSTEAM.DETAIL(“new_mem”)) OLD
REUS”
“EXECIO” data_in.0. “DISKW” new_mem “(STEM data_in. FINIS”
address HSCMDS “FREE F(“new_mem”)” - Modify <DETAIL COMBINED=...> tag to point to the replacement DETAIL member:
Modify an MQ script to test the requester
This section provides an example that shows how to modify an MQ script to test the requesting application. In this example, the application flow is as follows:
- The Customer Inquiry Program PUTs an inquiry to the request queue (PUT A).
- The Customer Information Processing Program GETs the request (GET A) and processes the inquiry.
- The processing program PUTs the response on the response queue (PUT B).
- The inquiry programs GETs the response from the response queue (GET B) and presents it to the user.
MQ Script Application Flow

The inquiry program assigns a unique correlation ID to the request message (PUT A). The correlation ID remains intact all of the way through processing. When the inquiry program retrieves the response (GET B), it uses the correlation ID to match the response with the request.
In this example, the user interface for the inquiry program must be tested to ensure that it is displaying information correctly, yet the processing program is unavailable.
To test the inquiry program, the player must act as the processing program. That is, it must execute GET A and PUT B. To do this, the request queue must contain a request that the player can GET (GET A). Input inquiries after playback starts to populate the queue. However, the correlation ID from the new requests will not match the correlation ID that was initially recorded. To make this scenario work, the player must replace the recorded correlation ID with the new correlation ID.
Further, thorough testing requires displaying several customer records. Achieve this by replacing the customer information in the recorded response (PUT B) with information from an external file. Each time you submit an inquiry, playback GETs the request and returns a response generated from the records in the external file. Add logic that terminates playback if the GET is unsuccessful or after all of the records have been used.
Start with a script that contains the processing program’s activity, GET A and PUT B (see the below figures). Then add REXX logic to:
- Initialize a Count Variable
- Read Data from an External File
- Loop Until an Unsuccessful GET or Last Record is Encountered
- Process the MQ_PUT Message
Each of these sections explains the REXX logic required to achieve the example and indicates where in the script to add the logic. Each section presents the relevant portion of the script along with the additional logic in bold text. If you have trouble with context, compare the section with the below figures. They show the script as it was recorded.
Page 1 of Script containing GET A and PUT B as Recorded
* SCRIPT STARTED ON 2007/02/13 AT 11:12:01
* DESC:
*
<VERSION>07.01.00
<DETAIL COMBINED='*'>
*
* MQ_CONNECT *
*
<TIME>2007/02/13_10:56:01.327075
<MQ_CONNECT,
CONNECTION_ID = 2,
COMPCODE = 0,
REASON = 0,
QMGR_NAME = 'QMGR',
SYSTEM_NAME = 'SYS1',
JOBNAME = 'JOB',
STIME = '2007/02/13_10:56:01.327075'>1
*
* MQ_OPEN *
*
<TIME>2007/02/13_10:56:01.325201
<MQ_OPEN,
CONNECTION_ID = 2,
OBJECT_ID = 3,
COMPCODE = 0,
REASON = 0,
MQOO = (FAIL_IF_QUIESCING,SAVE_ALL_CONTEXT,INPUT_SHARED),
MQOD_VERSION = 3,
MQOD_OBJECTNAME_OUT = 'CLIENT.REQUEST.QUEUE',
MQOD_OBJECTNAME_IN = 'CLIENT.REQUEST.QUEUE',
MQOD_OBJECTQMGRNAME = '',
MQOD_DYNAMICQNAME = 'CSQ.*'>2
*
* MQ_OPEN *
*
<TIME>2007/02/13_10:56:01.323695
<MQ_OPEN,
CONNECTION_ID = 2,
OBJECT_ID = 2,
COMPCODE = 0,
REASON = 0,
MQOO = (FAIL_IF_QUIESCING,PASS_ALL_CONTEXT,OUTPUT),
MQOD_VERSION = 3,
MQOD_OBJECTNAME_OUT = 'CUSTOMER.RESPONSE.QUEUE',
MQOD_OBJECTNAME_IN = 'CUSTOMER.RESPONSE.QUEUE',
MQOD_OBJECTQMGRNAME = '',
MQOD_DYNAMICQNAME = 'CSQ.*'>3
*
* MQ_GET *
*
<TIME>2007/02/13_10:56:01.327075
<MQ_GET,
CONNECTION_ID = 2,
OBJECT_ID = 3,
COMPCODE = 0,
REASON = 0,
MQMD_EXPIRY = '00001387'X,
MQMD_ENCODING = '00000222'X,
MQMD_CODEDCHARSETID = 437,
MQMD_FORMAT = 'MQSTR',
MQMD_PRIORITY = '',
MQMD_PERSISTENCE = NOT_PERSISTENT,
MQMD_MSGID = '000000000000000000000000000000000000000000000000'X,
MQMD_BACKOUTCOUNT = '',
MQMD_REPLYTOQMGR = 'QMGR',
MQMD_USERIDENTIFIER = 'ASPNET',
MQMD_ACCOUNTINGTOKEN = '000000000000000000000000000000000000000000000000'X,
MQMD_PUTAPPLTYPE = WINDOWS_NT,
MQMD_PUTAPPLNAME = 'APPL',
MQMD_PUTDATE = '20070213',
MQMD_PUTTIME = '15560215',
MQGMO_VERSION = 3,
Page 2 of Script Containing GET A and PUT B as Recorded
MQGMO_RESOLVEDQNAME = 'CLIENT.REQUEST.QUEUE',
CRNTLEN = 49,
TRUELEN = 49,
TRANSLATE=A2E>4
*
* MQ_PUT *
*
<TIME>2007/02/13_10:56:03.799357
<MQ_PUT,
CONNECTION_ID = 2,
OBJECT_ID = 2,
COMPCODE = 0,
REASON = 0,
MQMD_EXPIRY = '00001388'X,
MQMD_FORMAT = 'MQSTR',
MQMD_PERSISTENCE = NOT_PERSISTENT,
MQMD_MSGID = '000000000000000000000000000000000000000000000000'X,
MQMD_CORRELID = 'C3E2D840D7D4D8D44040404040404040BC70741C817B6021'X
MQMD_BACKOUTCOUNT = '',
MQMD_USERIDENTIFIER = 'ASPNET',
MQMD_ACCOUNTINGTOKEN = '1A0FD4F5F2F0C3C8C9D5F3F9F8C2F7C3F3F000398B7C300000000'X,
MQMD_PUTAPPLTYPE = WINDOWS_NT,
MQMD_PUTAPPLNAME = '',
MQMD_PUTDATE = '20070213',
MQMD_PUTTIME = '15560215',
MQPMO_OPTIONS = (FAIL_IF_QUIESCING,PASS_ALL_CONTEXT,NO_SYNCPOINT),
MQPMO_RESOLVEDQNAME = 'CLIENT.RESPONSE.QUEUE',
MQPMO_RESOLVEDQMGRNAME = 'QMGR',
CRNTLEN = 1000,
TRUELEN = 1000>6
<CONTENT> þ 000000020000000000000000000000000000 000000000
*
* MQ_CLOSE *
*
<TIME>2007/02/13_10:56:03.802374
<MQ_CLOSE,
CONNECTION_ID = 2,
OBJECT_ID = 2,
COMPCODE = 0,
REASON = 0,
MQCO = (NONE)>8
*
* MQ_CLOSE *
*
<TIME>2007/02/13_10:56:03.801748
<MQ_CLOSE,
CONNECTION_ID = 2,
OBJECT_ID = 3,
COMPCODE = 0,
REASON = 0,
MQCO = (NONE)>7
*
* MQ_DISCONNECT *
*
<TIME>2007/02/13_10:56:03.823516
<MQ_DISCONNECT,
CONNECTION_ID = 2,
COMPCODE = 0,
REASON = 0>9
Initialize a Count Variable
The looping logic in this example requires a count variable. At the beginning of the script, after the <VERSION> tag, initialize the variable.
* DESC:
*
<VERSION>07.01.00
<DETAIL COMBINED='*'>
i= 0
Read Data from an External File
Reading data from the external file is the next required step. After variable initialization, before the connection is established, insert an EXECIO statement to read the records into a REXX stem variable, ‘reply_message’. This results in a series of reply_message.n variables, where n indicates the record number. Include a FINIS parameter to close the file after all of the records have been read.
*
* MQ_CONNECT *
*
<TIME>2007/02/13_10:56:01.327075
<MQ_CONNECT,
CONNECTION_ID = 2,
COMPCODE = 0,
REASON = 0,
QMGR_NAME = 'QMGR',
SYSTEM_NAME = 'SYS1',
JOBNAME = 'JOB',
STIME = '2007/02/13_10:56:01.327075'>1
*
* MQ_OPEN *
*
<TIME>2007/02/13_10:56:01.325201
<MQ_OPEN,
CONNECTION_ID = 2,
OBJECT_ID = 3,
COMPCODE = 0,
REASON = 0,
MQOO = (FAIL_IF_QUIESCING,SAVE_ALL_CONTEXT,INPUT_SHARED),
Loop Until an unsuccessful GET or last record is encountered
Because the script contains only a single transaction, looping logic must be added to the script to execute the GET and process the response message the correct number of times. If the GET is unsuccessful or there are no more records to process, the loop must terminate. To do this:
- Before the MQ_GET tag that retrieves the request, insert a DO statement to execute the MQ_GET until all records have been processed (DO i=1 TO replay_message.0). ‘reply_message.0’ represents the total number of records.
- Add a WAIT parameter to the MQGMO_OPTIONS to avoid executing multiple MQ_GETS on an empty queue.
- After the MQ_GET tag, insert an IF statement that checks the reason code to ensure that the GET is successful. Use the Performance Test for WebSphere MQ REXX variable ACTUAL_REASON to return the reason code. If the reason code equals zero, increment the count and set the length value (new_len) used for processing the response message to the length of the current record (reply_message.i).
- After the MQ_PUT that delivers the response, insert an END statement that ends the current loop and returns to the beginning of the DO loop, providing the IF statement condition is met. That is, the MQ_GET is successful.
- After the END statement, insert an ELSE statement that terminates the loop if the MQ_GET is unsuccessful. To terminate the loop, set the value of i to ‘reply_message.0’.
- After the ELSE statement, insert another END statement to terminate the DO loop when all records from the external file have been processed.
* MQ_GET *
*
<TIME>2007/02/13_10:56:01.327075
<MQ_GET,
CONNECTION_ID = 2,
OBJECT_ID = 3,
COMPCODE = 0,
REASON = 0,
MQMD_EXPIRY = '00001387'X,
MQMD_ENCODING = '00000222'X,
MQMD_CODEDCHARSETID = 437,
MQMD_FORMAT = 'MQSTR',
MQMD_PRIORITY = '',
MQMD_PERSISTENCE = NOT_PERSISTENT,
MQMD_MSGID = '000000000000000000000000000000000000000000000000'X,
MQMD_BACKOUTCOUNT = '',
MQMD_REPLYTOQMGR = 'QMGR',
MQMD_USERIDENTIFIER = 'ASPNET',
MQMD_ACCOUNTINGTOKEN = '00000000000000000000000000000000000000000000'X,
MQMD_PUTAPPLTYPE = WINDOWS_NT,
MQMD_PUTAPPLNAME = 'APPL',
MQMD_PUTDATE = '20070213',
MQMD_PUTTIME = '15560215',
MQGMO_VERSION = 3,
MQGMO_OPTIONS = (WAIT,CONVERT,NO_SYNCPOINT),
MQGMO_RESOLVEDQNAME = 'CLIENT.REQUEST.QUEUE',
CRNTLEN = 49,
TRUELEN = 49,
TRANSLATE=A2E>4
IF ACTUAL_REASON = 0 THEN DO i = i + 1 new_len = LENGTH(reply_message.i)*
* MQ_PUT *
*
<TIME>2007/02/13_10:56:03.799357
<MQ_PUT,
CONNECTION_ID = 2,
OBJECT_ID = 2,
COMPCODE = 0,
REASON = 0,
MQMD_EXPIRY = '00001388'X,
MQMD_FORMAT = 'MQSTR',
MQMD_PERSISTENCE = NOT_PERSISTENT,
MQMD_MSGID = '000000000000000000000000000000000000000000000000'X,
MQMD_CORRELID = 'C3E2D840D7D4D8D44040404040404040BC70741C817B6021'X
MQMD_BACKOUTCOUNT = '',
MQMD_USERIDENTIFIER = 'ASPNET',
MQMD_ACCOUNTINGTOKEN = '1A0FD4F5F2F0C3C8C9D5F3F9F8C2F7C3F3F000398B7C3'X,
MQMD_PUTAPPLTYPE = WINDOWS_NT,
MQMD_PUTAPPLNAME = '',
MQMD_PUTDATE = '20070213',
MQMD_PUTTIME = '15560215',
MQPMO_OPTIONS = (FAIL_IF_QUIESCING,PASS_ALL_CONTEXT,NO_SYNCPOINT),
MQPMO_RESOLVEDQNAME = 'CLIENT.RESPONSE.QUEUE',
MQPMO_RESOLVEDQMGRNAME = 'QMGR',
CRNTLEN = 1000,
TRUELEN = 1000>6
<CONTENT> þ 000000020000000000000000000000000000 000000000
END ***Response is complete, return to MQ_GET Loop ELSE i=reply_message.0 ***GET failed, set value of i to terminate loopEND ***End of external file, terminate loop
Process the MQ_PUT message
The correlation ID that was recorded must be replaced with the correlation IDs from the live requests that are in the request queue. Additionally, the recorded response message must be replaced with the records from the external file.
- Before the MQ_PUT tag that delivers the response and after the IF statement added in the last step, initialize a variable with the value of the current request’s correlation ID. Use the Performance Test REXX variable ACTUAL_CORRELID to return the actual correlation ID from the preceding MQ_GET. The correlation ID must be enclosed in single quotes and followed by the letter X to signify hexadecimal format. Therefore, the opening single quote, and the closing single quote and letter X, must be enclosed in double quotation marks.
- Inside the MQ_PUT tag, replace the value of the MQMD_CORRELID parameter with the NEW_CORRELID variable.
- Above the CONTENT tag associated with the MQ_PUT, insert the REPLACE tag to replace the recorded customer information with the current record from the external file (reply_message.i). The REPLACE tag requires a FIELD parameter that defines the offset and replacement value. It also supports an optional LENGTH parameter. Set the offset to 0 to begin replacing data with the first byte, set the replacement value to reply_message.i, which is the current record, and set the length value to new_len, which is the length of the current record.
* MQ_PUT *
*
<TIME>2007/02/13_10:56:03.799357
<MQ_PUT,
CONNECTION_ID = 2,
OBJECT_ID = 2,
COMPCODE = 0,
REASON = 0,
MQMD_EXPIRY = '00001388'X,
MQMD_FORMAT = 'MQSTR',
MQMD_PERSISTENCE = NOT_PERSISTENT,
MQMD_MSGID = '000000000000000000000000000000000000000000000000'X,
MQMD_CORRELID = NEW_CORRELID, MQMD_BACKOUTCOUNT = '',
MQMD_USERIDENTIFIER = 'ASPNET',
MQMD_ACCOUNTINGTOKEN = '1A0FD4F5F2F0C3C8C9D5F3F9F8C2F7C3F3F000398B7C3'X,
MQMD_PUTAPPLTYPE = WINDOWS_NT,
MQMD_PUTAPPLNAME = '',
MQMD_PUTDATE = '20070213',
MQMD_PUTTIME = '15560215',
MQPMO_OPTIONS = (FAIL_IF_QUIESCING,PASS_ALL_CONTEXT,NO_SYNCPOINT),
MQPMO_RESOLVEDQNAME = 'CLIENT.RESPONSE.QUEUE',
MQPMO_RESOLVEDQMGRNAME = 'QMGR',
CRNTLEN = 1000,
TRUELEN = 1000>6
<REPLACE FIELD(0,reply_message.i) LENGTH=new_len> <CONTENT> þ 000000020000000000000000000000000000 000000000
END ***Response is complete, return to MQ_GET Loop
ELSE
i=reply_message.0 ***GET failed, set value of i to terminate loop
END ***End of external file, terminate loop
*
* MQ_CLOSE *
*
<TIME>2007/02/13_10:56:03.802374
<MQ_CLOSE,
CONNECTION_ID = 2,
OBJECT_ID = 2,
COMPCODE = 0,
REASON = 0,
MQCO = (NONE)>8
*
* MQ_CLOSE *
*
<TIME>2007/02/13_10:56:03.801748
<MQ_CLOSE,
CONNECTION_ID = 2,
OBJECT_ID = 3,
COMPCODE = 0,
REASON = 0,
MQCO = (NONE)>7
*
* MQ_DISCONNECT *
*
<TIME>2007/02/13_10:56:03.823516
<MQ_DISCONNECT,
CONNECTION_ID = 2,
COMPCODE = 0,
REASON = 0>9