Japanese

Practical mastering IBM MQ basics

Message descriptor (MQMD) (1)

*This series may be revised based on the latest mqpgf/mqpcf. Please always download and use the latest version.

In this series, we will explain the basics of WebSphere MQ/IBM MQ through functional verification of IBM MQ using mqpgf/mqpcf which is Software created/provided by us.

mqpgf is a program that can perform various tests using MQI, APIs provided by MQ. It interacts with the queue manager through the qmgr agent process.

fig 1.1

mqpcf is a program that can send and receive PCF commands with the command server using MQAI, an MQ management API, execute operations on MQ objects, and check their status.

fig 1.2

Please refer to the mqpgf User's Guide, the mqpcf User's Guide, and the MQ Knowledge Center, as needed. mqpgf / mqpcf can be downloaded from this site, there is no installation, and it is only necessary to extract the downloaded archive and copy the command. For details, refer to the documents included in the downloaded archive. The installation of MQ will not be described in this series, so please refer to the product manual. Even if you do not have a license for IBM MQ, you can use the "Free Evaluation (90 days)" and "WebSphere MQ Advanced for development" under certain conditions. This series is mainly confirmed by MQ 9.x and MQ8.x, but with MQ 5.3 or later, it should be possible to execute without problems except for some functions such as message properties.

*In the case of MQ for HP NonStop product, some operations may differ from those described in this series.


Usage of mqpgf and mqpcf command

First, I will introduce how to display the options that can be specified in mqpgf and mqpcf.


1) mqpgf

With no arguments, mqpgf will display the options that can be specified.

$ mqpgf -qm : queue manager name(e.g. -qm qm1,qm2,...) -q : queue name -m : input message -mx : input message(hexadecimal notation e.g. 09af..) -f : input file name -o : output file name -oq : output queue name(for queue to queue)('*': ReplyToQ, '**': + ReplyToQMgr) -iq : input queue name(for send and receive) -d : input directory name -g : output directory name -r : get repeatedly -b : force backout -l : message length for writing -n : message count for writing or reading -i : interval(ms) for writing or reading -sz : max message size for reading(byte)(default 12KByte) -ds : max message display size(byte)(default 128Byte) (all: entire message) -br : browse message -brv : browse message(verbose) -dp : dump message -dpv : dump message(verbose) -raw : raw mode output -hex : dump hexadecimal -s : stop before MQI call (e.g. -s MQCMIT) -p : process name -nl : namelist -pcf : pcf format file name -ss : switch to parameters for secondary -sp : switch to parameters for primary -mc : get the message with the same CorrelId as MsgId sent -im : Inherit MQMD -as : segmentation size -dl : delimiter for logical messages -nt : number of threads -ni : number of threads that call MQCONN/MQDISC internally -tr : enable api trace -sf : the file for synchronization start -c : connection loop count -sd : skip MQDISC -wp : wait time to next processing -ca : continue processing after MQCONN(X) fails -ac : applend the counter to message automatically -cr : The number of connection retry -y : Invoke yield function after every MQI call Platform-specific options : -gt : Using Global UOW for NSK -gti : Using Global UOW for NSK(TMFAPI: per PUT/GET) MQI functions : -set : MQSET (e.g. MQIA_INHIBIT_GET:MQQA_GET_ALLOWED,..:..) -inq : MQINQ (e.g. MQCA_ALTERATION_DATE,MQIA_CLWL_Q_PRIORITY,..) -smp : MQSETMP (e.g. MQTYPE_STRING:property name:value,..:..) MQCD fields (use MQCONNX) : -x : ConnectionName (e.g. -x "localhost(1414)") -ch : ChannelName -la : LocalAddress -cl : CertificateLabel -cs : SSLCipherSpec -er : SSLPeerName MQMD fields : -ex : Expiry(par 100ms) -ec : Encoding -cc : CodedCharSetId -pr : Priority -mi : MsgId -ci : CorrelId -rq : ReplyToQ -rm : ReplyToQMgr -ui : UserIdentifier -at : AccountingToken -ap : ApplIdentityData -pn : PutApplName -pd : PutDate -pt : PutTime -ao : ApplOriginData MQMD Version 2 fields : -gi : GroupId -ms : MsgSeqNumber -of : Offset -ol : OriginalLength MQRFH2 fields: -re : Encoding( or MQENC_*) -rc : CodedCharSetId( or MQCCSI_*) -rf : Format(e.g. -rf MQFMT_STRING) -fg : Flags -nc : NameValueCCSID( or MQCCSI_*) -nd : NameValueData(e.g. -nd "data1,data2,data3") MQCSP fields: -cu : CSPUserId -cp : CSPPassword MQOD fields: -om : ObjectQMgrName -au : AlternateUserId -or : ObjectRec(MQOR)(e.g. ObjectName:ObjectQMgrName,..:..,...) -dq : DynamicQName(for receive queue, e.g. "DQ*", "*" or 33bytes full name) MQPMO fields: -mr : PutMsgRec(MQPMR)(e.g. :::MQFB_xx:,..) MQGMO fields: -wi : WaitInterval(ms) -mt : MsgToken MQIMPO fields: -pe : RequestedEncoding( or MQENC_*) -pc : RequestedCCSID( or MQCCSI_*) MQCB fields : -op : Operation (e.g. -op MQOP_REGISTER -op MQOP_SUSPEND ...) MQCBD fields: -cf : CallbackFunction (e.g. EventHandler) Constants: MQMD : MQMD_*, MQRO_*, MQMT_*, MQEI_*, MQFB_*, MQENC_*, MQCCSI_*, MQFMT_*, MQPRI_*, MQPER_*, MQMI_*, MQCI_*, MQACT_*, MQACTT_*, MQAT_* MQMDV2 : MQGI_*, MQMF_*, MQOL_* MQRFH2 : MQRFH_* MQCONNX : MQCNO_*, MQCSP_*, MQCD_* MQOPEN : MQOO_*, MQOT_*, MQOD_* MQPUT : MQPMO_*, MQPMRF_* MQGET : MQGMO_*, MQWI_*, MQMO_* MQCLOSE : MQCO_* MQSETMP : MQPD_* MQINQMP : MQIMPO_* MQCRTMH : MQCMHO_* MQCB : MQCBT_*

*If you specify "-v", version information is displayed. $ mqpgf -v ・・・・ [ License information ] Expires 2021.10.31 version 1.4.2.8 2021/03/10 library version 1.0.0.1 2021/03/10

*If "all" is specified further, a list of specifiable MQ constants will be displayed. $ mqpgf -v all .... MQMD_VERSION_1 MQMD_VERSION_2 MQMD_CURRENT_VERSION MQRO_EXCEPTION ....


2) mqpcf

With no arguments, mqpcf will display the options that can be specified.

*If "-v" is specified, version information is also displayed.


$ mqpcf -v USAGE : mqpcf qmgr -qm Qmgr mqpcf qms -qm Qmgr mqpcf que -qm Qmgr mqpcf cque -qm Qmgr mqpcf ques -qm Qmgr mqpcf queh -qm Qmgr mqpcf chl -qm Qmgr mqpcf chs -qm Qmgr mqpcf lsnr -qm Qmgr mqpcf lsst -qm Qmgr mqpcf cqmgr -qm Qmgr mqpcf con -qm Qmgr mqpcf pngm -qm Qmgr mqpcf ping -qm Qmgr -c Channel mqpcf {put | get} {enable | disable} -qm Qmgr -q Queue mqpcf clr -qm Qmgr -q Queue mqpcf rst -qm Qmgr -c Channel mqpcf rslv -qm Qmgr -c Channel {commit | backout} mqpcf sta -qm Qmgr -c Channel mqpcf stp -qm Qmgr -c Channel mqpcf stalsn -qm Qmgr -ln Listener mqpcf stplsn -qm Qmgr -ln Listener mqpcf mqsc -qm Qmgr {-f MqscFile | -s 'Mqcmd'} -rc : repeat count -i : repeat interval(sec) -t : display time -wi : The maximum time(sec) that the MQAI waits for each reply message -cu : UserId -ci : Password select parameters to display(e.g. mqpcf chs .. SUBSTATE MCASTAT) [ License information ] Expires 2021.11.30 version 1.4.0.11 2021.09.10 library version 1.0.0.1 2021/03/10

Also, if you specify only a command to execute, the options available for that command will be displayed. $ mqpcf put USAGE : mqpcf {put | get} {enable | disable} -qm Qmgr -q Queue

to the top

Message descriptor (MQMD) overview

MQ messages always have a structure called a message descriptor (MQMD: MQ Messege Descriptor). Various MQ functions can be used by setting and referencing each field of this structure. In many cases, since the message and system linkage were designed without understanding this well, the benefits of that functions can not be obtained, and the same functions provided by MQ have been implemented in the application or system side. Before starting to design the MQ integration system and decide on the format of the message, be sure to understand its capabilities.

fig 1.3

Below is a list of fields in MQMD. Version 1 and Version 2 exist in MQMD. Version 2 adds some fields / features.


field Description
StrucId Structure ID
Version Structure version number
Report Report message options
MsgType Message type
Expiry Message expiration time
Feedback Feedback or Reason code
Encoding Numeric encoding of message data
CodedCharSetId Coded Character set identifier of message data
Format Format name of message data
Priority Message priority
Persistence Message persistence
MsgId Message ID
CorrelId Correlation ID
BackoutCount Backout counter
ReplyToQ Name of response queue
ReplyToQMgr Name of response queue manager
UserIdentifier User ID
AccountingToken Accounting token
ApplIdentityData Application data associated with the identifier
PutApplType Type of application that wrote the message
PutApplName Name of the application that wrote the message
PutDate Date you wrote the message
PutTime Time you wrote the message
ApplOriginData Application data related to the origin

*Below are the fields added with MQMD_VERSION_2.
GroupId Group ID
MsgSeqNumber Sequence number of logical message in group
Offset Relative position of physical message data from the start of the logical message
MsgFlags Message flags
OriginalLength Original message length


mqpgf can set / reference all MQMD fields that are authorized for the user. If not specified, mqpgf sets the default value to MQMD. MQ defines the initial value of MQMD structure with MQMD_DEFAULT. Specific values ??of the initial value of MQMD structure will be introduced later, but please refer to the product manual if necessary.


Creating a test queue manager and performing basic tests

So, actually put a message on the queue and check the MQMD of that message.

First, create a queue manager and a queue for test , and start the command server.

fig 1.4

Work using the MQ administration user who belongs to the mqm group.

Create a queue manager SampleQM.

*In MQ for HP NonStop, the parameters passed to crtmqm are different from other platforms. Please refer to the product manual for details.

$ crtmqm SampleQM
WebSphere MQ queue manager created.
....

Start the created queue manager.

$ strmqm SampleQM
IBM MQ queue manager 'SampleQM' starting.
IBM MQ queue manager 'SampleQM' started using V8.0.0.0.


*The command to end a queue manager is "endmqm <queue manager name>".

mqpcf uses a command server. In the new version of MQ, since the command server is synchronized with starting and stopping of the queue manager by default, starting the queue manager will also start the command server. If you are using an older level of MQ, such as WebSphere MQ for HP NonStop 5.3, or if your environment's queue manager has not intentionally started the command server, you have to start the command server manually.

$ strmqcsv SampleQM
IBM MQ command server started.


cf. If the queue manager's SCMDSERV property is set to "MANUAL", If you change it to "QMGR" (default), the command server will also be started at the same time QMGR starts.

   $ runmqsc SampleQM
   
   MQSC > dis qmgr scmdserv
   5 : dis qmgr scmdserv
   AMQ8408: Display Queue Manager details.
   QMNAME(SampleQM) SCMDSERV(MANUAL)
   
   MQSC > alter qmgr scmdserv(QMGR)
    6 : alter qmgr scmdserv(QMGR)
   AMQ8005: IBM MQ queue manager changed.
   MQSC > end
   $

Create a queue named SampleQ for testing.

$ runmqsc SampleQM
....
MQSC > def ql('SampleQ')
1 : def ql('SampleQ')
AMQ8006: WebSphere MQ queue created.
MQSC > end
$

*When using lowercase letters in MQSC command, it is necessary to enclose the string by single quote. Otherwise, all letters will be converted to uppercase.


Ex. 1.1 Execution of PUT / GET and dump display of messages

Now use mqpgf to PUT a test message.

$ mqpgf -qm SampleQM -q SampleQ -m "sample message"
[18/01/24 11:00:28] 1: message length: 14 put message : sample message

*Option descriptions
-qm: queue manager name
-q: Target queue name
-m: message to put

*In the case of HP NonStop, the request functions in the unit of work (MQPMO_SYNCPOINT) by default. The unit of work (MQPMO_NO_SYNCPOINT) is the default on all other platforms. Therefore, when PUT / GET is executed on HP NonStop, mqpgf calls MQCMIT() API and commits the PUT / GET request. The following message is additionally displayed.

MQCMIT success : CompCd=00 ReasonCd=00

Next, GET the put message in browse mode (MQOO_BROWSE) and dump the message. Browse mode does not clear messages from the queue after reading them.

fig 1.5


Test result 1.1

$ mqpgf -qm SampleQM -q SampleQ -br
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[819] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A67E3D520002805] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180124] PutTime[04085314] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 14
00000000: 7361 6D70 6C65 206D 6573 7361 6765 'sample message '

*Option descriptions
-br: GET messages in browse mode

When -br is specified, MQMD is displayed for each field, and the other part is displayed with hexadecimal dump and visible character. The MQMD displayed above shows the value set when put using MQMD_DEFAULT.

The description for each field also describes the type, size, initial value, and whether the field is input or output. The meaning of the input and output here may be confused, so I will explain in advance

The following is the call syntax of MQPUT() and MQGET() API.

MQPUT (Hconn, Hobj, MsgDesc, PutMsgOpts, BufferLength, Buffer, CompCode, Reason)
MQGET (Hconn, Hobj, MsgDesc, GetMsgOpts, BufferLength, Buffer, DataLength, CompCode, Reason)

Both MQPUT() and MQGET() have MsgDesc (MQMD) as an argument, and both are input / output parameters. And I / O is decided for each field of MQMD. This meaning is input / output seen from API. For example, MQMD has a field called PutTime. When MQPUT() is called, this field is an output field by default, and the input (value specified when calling the API) is ignored, and the time when the message was written is set by GMT (Greenwich Mean Time) after putting. It will be returned to the application (output). In the case of a fixed input field, the value shown after calling MQGET() still the value specified(input) before the call and it does not indicate the value on the message(outputs).

to the top

MQMD Fields

So, I explain the fields of MQMD one by one.

[ StrucId ]

Type: MQCHAR4
Size: 4 bytes
Initial value: MQMD_STRUC_ID_ARRAY("MD ")
Input/output: input

The ID of the MQMD structure, fixed as "MD".
Each MQ structure has an ID field at the top that indicates the structure.

[ Version ]

Type: MQLONG
Size: 4 bytes
Initial value: MQMD_VERSION_1(1)
Input / outpu: input

As mentioned earlier, there are currently two versions of MQMD: MQMD_VERSION_1 and MQMD_VERSION_2. I may be asked how to read and check this field, as the version used by the destination system that created the message may be different. However, unfortunately this field is always an input field as described at the beginning, so it is not possible to check the value on the message. The value set after the MQGE () call is the same as the value set before the call. Here, when "Test Result 1.1" is confirmed, "Version [2]" is displayed. If you use mqpgf with PUT by default, use MQMD_DEFAULT and its value is MQMD_VERSION_1. However, when displaying dumps (when "-br", "-brv", "-dp" or "-dpv" is specified), MQMD_VERSION_2 is used instead of the default value exceptionally. So, "Test Result 1.1" only shows the value specified in the input.


Ex. 1.2 GET with specifing the MQMD version

If you want to call MQGET() with MQMD_VERSION_1 specially, specify "MQMD_VERSION_1" in the command line argument as shown below.


Test result 1.2

$ mqpgf -qm SampleQM -q SampleQ -br MQMD_VERSION_1
message number: 1
*StrucId[MD ] Version[1] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[819] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A67E3D520002805] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180124] PutTime[04085314] ApplOriginData[ ]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 14
00000000: 7361 6D70 6C65 206D 6573 7361 6765 'sample message '

*Option descriptions
MQMD_VERSION_1: Use MQMD Ver1.

This is a browse of the same message as Test Results 1.1. It can be confirmed by the same MsgId value (MsgId is described later). However, Version field shows "Version [1]". If you get a message by specifying MQMD_VERSION_1, if you try to read GroupId, MsgSeqNumber, Offset, MsgFlags, OriginalLength, which are specific fields of MQMD_VERSION_2, these default values will be returned. If MQMD_VERSION_1 is specified in MQGET( ), and the Version 2 field is used (it is not the default value), an MQMDE (Extended Message Descriptor) header is generated and in that header the value of MQMD_VERSION_2 specific fields is returned. Detailed explanation of MQMDE is omitted here. If a queue have a mix of messages with MQMD_VERSION_1 or MQMD_VERSION_2, you should always call MQGET() with MQMD_VERSION_2. When the message with MQMD_VERSION_1 is read with MQMD_VERSION_2 specified, the default values are set to the MQMD_VERSION_2 specific fields and returned to the application.

MQMD Version
of the message
V2 field value
of the message
Specified MQMD Version
when MQGET called
Value returned
in V2 field
MQMDE
MQMD_VERSION_1 - MQMD_VERSION_1 Default value None
MQMD_VERSION_1 - MQMD_VERSION_2 Default value None
MQMD_VERSION_2 Default MQMD_VERSION_1 Default value None
MQMD_VERSION_2 Other than default MQMD_VERSION_1 Default value Generate *
MQMD_VERSION_2 Any MQMD_VERSION_2 The value of the message None
*The value of the MQMD V2 field is set.

fig 1.6

[ Report ]

Type: MQLONG
Size: 4 bytes
Initial value: MQRO_NONE(0)
Input / output: MQGET(): Output, MQPUT(): Input

The report option is used to request a report message to check if the message has been successfully transferred / processed. There are the following types.


Report type Origin
exception MCA
expiration date Queue manager
Confirm On Arrival (COA) Queue manager
Confirm On Delivery (COD) Queue manager
Positive Action Notification (PAN) Receiver application
Negative Action Notification (NAN) Receiver application

Except for PAN / NAN, MCA or Queue Manager automatically generates report messages. The content / result of the report message is shown in the "Feedback" field described later. The "Correlation ID Option" is used to associate the report message with the sender's message.

For example, specify “Confirm On Arrival (COA) (MQRO_COA)” and “Confirm On Delivery (COD) (MQRO_COD_WITH_FULL_DATA)” as “type of report”, and use MQRO_COPY_MSG_ID_TO_CORREL_ID (default) as "correlation ID option". In addition, specify MQMT_REQUEST (a message that requires a response) as the message type.

MQRO_COA and MQRO_COD_WITH_FULL_DATA are set in the MQMD.Report field with their respective OR. mqpgf will do this automatically if you specify these two as arguments. Since MQRO_COPY_MSG_ID_TO_CORREL_ID is defined 0x00000000 and it becames effective when MQRO_PASS_CORREL_ID is not set, it is not nesesary to set MQRO_COPY_MSG_ID_TO_CORREL_ID.


Create a connection to the opposite side queue manager

Create opposing queue managers and queues, listeners, and channels for testing. The queue manager can be created on the same machine if there is no additional environment.

fig 1.7

Create the opposite side queue manager RemoteQM.

*In MQ for HP NonStop, the parameters passed to crtmqm are different from other platforms. Please refer to the product manual for details.

$ crtmqm RemoteQM
WebSphere MQ queue manager created.
....

Start the created queue manager.

$ strmqm RemoteQM
IBM MQ queue manager 'RemoteQM' starting.
IBM MQ queue manager 'RemoteQM' started using V8.0.0.0.

*If the command server has not been started, start it in the same way as SampleQM.

Create a queue RemoteQ for testing.

$ runmqsc RemoteQM
....
MQSC > def ql('RemoteQ')
1 : def ql('RemoteQ')
AMQ8006: IBM MQ queue created.

Create and start a listener on each queue manager. If RemoteQM is created on another machine, the port can be the same as SampleQM 1414 (default). If you use control (qmgr) th parameter of listner, the listener will also be started / stopped as the queue manager is started / stopped.

*In the case of WebSphere MQ 5.3 for HP NonStop, the listener is usually configured as a server class of Pathway.

<< Working with SampleQM >>

Create a listener

MQSC > def listener(listener) trptype(tcp) port(1414) control(qmgr)
1 : def listener(listener) trptype(tcp) port(1414) control(qmgr)
AMQ8626: IBM MQ listener created.

Start the created listener.

$ mqpcf stalsn -qm SampleQM -ln LISTENER
Listener Start Success. Listener Name : LISTENER

*Option descriptions
stalsn: execute "Start Channel Listener" command
-ln: listener name

*In case of WebSphere MQ 5.3 for HP NonStop, start the default TCP/IP listener from runmqsc.
$ runmqsc SampleQM
MQSC >sta listener
1 : sta listener
AMQ8021: WebSphere MQ Listener program started.
MQSC >end

Make sure that the listener has started.

$ mqpcf lsst -qm SampleQM -ln LISTENER STATUS
1: LISTENER(LISTENER) STATUS(RUNNING)

*Option descriptions
lsst: Execute "Inquire Channel Listener Status" command
STATUS: Display of STATUS field

*mqpcf can specify the field name to be displayed (like "STATUS" above) without options. In that case, only the parameters that are always returned by the PCF command and the specified field name are displayed.


<< Working with RemoteQM >>

MQSC > def listener(listener) trptype(tcp) port(1415) control(qmgr)
1 : def listener(listener) trptype(tcp) port(1415) control(qmgr)
AMQ8626: IBM MQ listener created.

In the following, start the listener as well as SampleQM and check that the status is "RUNNING".

Next, create a message channel bi-directionally between the two queue managers. The channel names are "Sample.TO.Remote" and "Remote.TO.Sample". Both ends of the channel must have the same name. Configure as follows. The type of channel to create is "SDR" on the sender side and "RCVR" on the receiver side.

SampleQM RemoteQM
Sample.TO.Remote(SDR) -> Sample.TO.Remote(RCVR)
Remote.TO.Sample(RCVR) <- Remote.TO.Sample(SDR)

<< Working with SampleQM >>

Create a queue (transmission queue) for channel transmission. In this case, use the same name as the destination queue manager name.

MQSC > def ql('RemoteQM') usage(xmitq)
4 : def ql('RemoteQM') usage(xmitq)
AMQ8006: IBM MQ queue created.

Create a sender channel. Specify the IP address or host name of the destination and the port number specified when creating the listener in conname.

MQSC > def chl('Sample.TO.Remote') chltype(sdr) conname('localhost(1415)') xmitq('RemoteQM')
8 : def chl('Sample.TO.Remote') chltype(sdr) conname('localhost(1415)') xmitq('RemoteQM')
AMQ8014: IBM MQ channel created.

Create a receiver channel.

MQSC > def chl('Remote.TO.Sample') chltype(rcvr)
11 : def chl('Remote.TO.Sample') chltype(rcvr)
AMQ8014: IBM MQ channel created.

Create a local definition of the remote queue, that is, a definition on SampleQM that points to the queue RemoteQ on RemoteQM.

MQSC > def qr('RemoteQ') rqmname('RemoteQM') rname('RemoteQ')
10 : def qr('RemoteQ') rqmname('RemoteQM') rname('RemoteQ')
AMQ8006: IBM MQ queue created.

The local definition of the remote queue has a parameter called XMITQ, which is not specified here. If not specified, a transmission queue with the same name as the target queue manager is used. (This time, the transmission queue name is created with the same name as the destination queue manager.)

<< Working with RemoteQM >>

Create a queue (transmission queue) for channel transmission. Make the same name as the destination queue manager name.

MQSC > def ql('SampleQM') usage(xmitq)
4 : def ql('SampleQM') usage(xmitq)
AMQ8006: IBM MQ queue created.

Create a sender channel.

MQSC > def chl('Remote.TO.Sample') chltype(sdr) conname('localhost(1414)') xmitq('SampleQM')
5 : def chl('Remote.TO.Sample') chltype(sdr) conname('localhost(1414)') xmitq('SampleQM')
AMQ8014: IBM MQ channel created.

Create a receiver channel.

MQSC > def chl('Sample.TO.Remote') chltype(rcvr)
6 : def chl('Sample.TO.Remote') chltype(rcvr)
AMQ8014: IBM MQ channel created

Once created, start the channel from each sender and check that the statuses are "RUNNING".

<< Working with SampleQM >>

$ mqpcf sta -qm SampleQM -c Sample.TO.Remote
Channel Start Success. Channel Name : Sample.TO.Remote

*Option descriptions
sta: Execute "Start Channel" command
-c: channel name

$ mqpcf chs -qm SampleQM -c Sample.TO.Remote STATUS
1: CHLINSTYPE(CURRENT) CHANNEL(Sample.TO.Remote) STATUS(RUNNING) CHLTYPE(SDR) CONNAME(127.0.0.1(1415)) RQMNAME(RemoteQM) STOPREQ(NO) SUBSTATE(MQGET) XMITQ(RemoteQM)

*Option Descriptions
chs: Execute "Inquire Channel Status" command

<< Working with RemoteQM >>

Similarly, start 'Remote.TO.Sample' and check the status.

$ mqpcf sta -qm RemoteQM -c Remote.TO.Sample
Channel Start Success. Channel Name : Remote.TO.Sample

$ mqpcf chs -qm RemoteQM -c Remote.TO.Sample STATUS
1: CHLINSTYPE(CURRENT) CHANNEL(Remote.TO.Sample) STATUS(RUNNING) CHLTYPE(SDR) CONNAME(127.0.0.1(1414)) RQMNAME(SampleQM) STOPREQ(NO) SUBSTATE(MQGET) XMITQ(SampleQM)

Make sure that the local definition of the remote queue is correctly defined and you can successfully transfer the message with 'Sample.TO.Remote'. Write any message to RemoteQ which is a local definition of remote queue on SampleQM.

$ mqpgf -qm SampleQM -q RemoteQ -m "transfer message"
[18/01/24 18:12:28] 1: message length: 16 put message : transfer message

Confirm that the transfer has been successfully executed by the fact that the number of messages (CURDEPTH) on RemoteQ, which is a local queue on RemoteQM, is "1".

$ mqpcf ques -qm RemoteQM -q RemoteQ CURDEPTH
1: QUEUE(RemoteQ) TYPE(QUEUE) CURDEPTH(1)

*Option Descriptions
ques: execute "Inquire Queue Status" command
CURDEPTH: Display of CURDEPTH field

Once you have confirmed the arrival of the message, clear the message.

$ mqpcf clr -qm RemoteQM -q RemoteQ
Clear Queue Success. Queue Name : RemoteQ

*Option Descriptions
clr: execute "Clear Queue" command

Finally, create a queue for receiving report messages.

<< Working with SampleQM >>

$ runmqsc SampleQM
....
MQSC > def ql('ReportQ')
1 : def ql('ReportQ')
AMQ8006: IBM MQ queue created.

The RemoteQ side does not require local definition of remote queues for sending report messages. If no remote queue local definition exists, then a transmission queue with the same name as the target queue manager is selected.


Ex. 1.3 Requesting and Receiving Report Messages

Please execute the following command. As MQRO_COPY_MSG_ID_TO_CORREL_ID of "correlation ID option" is the value 0x00000000 as mentioned above, it can be omitted.

$ mqpgf -qm SampleQM -q RemoteQ -m "mqmd.Report test" -rq ReportQ MQRO_COA MQRO_COD_WITH_FULL_DATA MQMT_REQUEST
[18/01/26 14:31:54] 1: message length: 16 put message : mqmd.Report test

*Option Descriptions
-rq: Specify MQMD.ReplyToQ
MQRO_COA: Confirm On Arrival (COA) (none of the application message data from the original message are included in the report message.)
MQRO_COD_WITH_FULL_DATA: Confirm On Delivery (COD) (all the application message data from the original message is included in the report message.)
MQMT_REQUEST: A message that requires a response

Confirm that the message has arrived at the target queue manager RemoteQ.

$ mqpcf ques -qm RemoteQM -q RemoteQ -t CURDEPTH
[18/01/26 14:32:11] 1: QUEUE(RemoteQ) TYPE(QUEUE) CURDEPTH(1)

*Option Description
-t: Display command execution time

The sender has been sent the report message Confirm On Arrival (COA) (MQRO_COA). I will confirm the contents later.

$ mqpcf ques -qm SampleQM -q ReportQ -t CURDEPTH
[18/01/26 14:32:17] 1: QUEUE(ReportQ) TYPE(QUEUE) CURDEPTH(1)

First, try dumping the message of RemoteQ of the target queue manager.


Test results 1.3.1

$ mqpgf -qm RemoteQM -q RemoteQ -brv
message number: 1
*StrucId[MD ] Version[2] Report[14592] MsgType[1] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[819] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A6AB4A020002902] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ReportQ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180126] PutTime[05315438] ApplOriginData[ ]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 16
00000000: 6D71 6D64 2E52 6570 6F72 7420 7465 7374 'mqmd.Report test'

*Option Description
-brv: GET messages in Detail Browse mode

"14592" is set for Report. This is 0x3900 in hexadecimal. This corresponds to the "OR" of the specified parameter below.

MQRO_COA 0x00000100 MQRO_COD_WITH_FULL_DATA 0x00003800 MQRO_COPY_MSG_ID_TO_CORREL_ID 0x00000000

In MsgType, as specified, the following value "1" corresponding to MQMT_REQUEST is set.

MQMT_REQUEST 1

ReplyToQ is a queue for receiving reports, and "ReportQ" is set as specified in the argument. ReplyToQMgr is a queue manager that receives reports. Since it was not specified, "SampleQM" which is a local queue manager is set.

Here, check the value set in MsgId.

This time, MQGET RemoteQM's RemoteQ messages, not browse.

$ mqpgf -qm RemoteQM -q RemoteQ
[18/01/26 14:32:30] 1: message length: 16 get message : mqmd.Report test

Verify that SampleQM has received a "Confirm On Delivery (COD) (MQRO_COD_WITH_FULL_DATA)".

$ mqpcf ques -qm SampleQM -q ReportQ -t CURDEPTH
[18/01/26 14:32:35] 1: QUEUE(ReportQ) TYPE(QUEUE) CURDEPTH(2)

CURDEPTH has become 2 cases.

You can confirm that "Confirm On Arrival (COA)" is generated when arriving at the opposite queue, and "Confirm On Delivery (COD)" is generated when the message is processed (MQGET) from the opposite queue.

Now, check the two report messages received by SampleQM.

If "-r" option is specified to mqpgf, all messages on the queue will be repeatedly retrieved.


Test result 1.3.2

$ mqpgf -qm SampleQM -q ReportQ -brv -r
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[4] Expiry[-1] Feedback[259] Encoding[273] CodedCharSetId[819] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512052656D6F7465514D202020205A6AB4B220002306] CorrelId[0x414D512053616D706C65514D202020205A6AB4A020002902] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[RemoteQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[7] PutApplName[RemoteQM ] PutDate[20180126] PutTime[05315443] ApplOriginData[ ]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 0
00000000: ' '

message number: 2
*StrucId[MD ] Version[2] Report[0] MsgType[4] Expiry[-1] Feedback[260] Encoding[273] CodedCharSetId[819] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512052656D6F7465514D202020205A6AB4B220002806] CorrelId[0x414D512053616D706C65514D202020205A6AB4A020002902] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[RemoteQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[7] PutApplName[RemoteQM ] PutDate[20180126] PutTime[05323011] ApplOriginData[ ]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 16
00000000: 6D71 6D64 2E52 6570 6F72 7420 7465 7374 'mqmd.Report test'

no message available : ReportQ CompCd=02 ReasonCd=2033

*Option Description
-r: GET messages repeatedly on queue

Both MsgType is set to "4". This corresponds to the following MQMT_REPORT and indicates that it is a report message.

MQMT_REPORT 4

The first message feedback field is "259" and the second is "260". This corresponds to the following values and indicates that the first case was COA and the second was COD.

MQFB_COA 259
MQFB_COD 260

Next, check the MsgId of the sent message of "Test Result 1.3.1" and the CorrelId of the report message.

Send Messge MsgId :[0x414D512053616D706C65514D202020205A6AB4A020002902] Report Message(1) CorrelId:[0x414D512053616D706C65514D202020205A6AB4A020002902] Report Message(2) CorrelId:[0x414D512053616D706C65514D202020205A6AB4A020002902]

The default MQRO_COPY_MSG_ID_TO_CORREL_ID behavior is to copy the MsgId of the request message to the CorrelId of the report message. You can see that the same value is copied exactly as it is. Although details will be described later, MQGET() can wait and GET only messages with a specific CorrelId. Along with that, this mechanism is an MQ function that is frequently used to link outgoing messages and reply messages.

Finally, about application data, the first message that did not request the original data with MQRO_COA is "data length: 0", and the second message that requested to include all the original data in the report data with MQRO_COD_WITH_FULL_DATA have 'mqmd.Report test' as it is. With "_WITH_DATA", only 100 bytes, with "_WITH_FULL_DATA" will produce a report message with all application data.

fig 1.7

[ MsgType ]

Type: MQLONG
Size: 4 bytes
Initial value: MQMT_DATAGRAM(8)
I/O: MQGET(): Output, MQPUT(): Input

There are the following types.

MQMT_DATAGRAM 8 Do not require a response message
MQMT_REQUEST 1 Message that needs a response
MQMT_REPLY 2 Response message to request
MQMT_REPORT 4 Report message

"Test result 1.1, 1.2" are used with MQMT_DATAGRAM(8), "Test result 1.3.1" is used with MQMT_REQUEST(1) and "Test result 1.3.2" is used MQMT_REPORT(4). Thus, these are different message types from each other.

Even in the MQ message of the system actually operated, sometimes these values are not specified correctly. To prevent confusion, when MQPUT(), specify MsgType that accurately represents the message.

to the top

to the top