pythonibm-mqpymqi

How can I configure CCSID value in my Queue Manager using "pymqi" Python library?


I'm currently developing an application which needs to connect a MQ Queue in order to have the queue saving message information inside another service. Once it's done, the service returns a result message through the MQ Queue and it is returned to me.

I'm sending a string message that contains a XML message similar to the following one:

<?xml version="1.0" encoding="UTF-8"?>
<peticionDemanda>
<subtipo>DEMANDA CONTRATACIÓN</subtipo>
</peticionDemanda>

It appears that MQ is not decoding properly the "Ó" character and "subtipo" field is being saved as "DEMANDA CONTRATACI├ôN".

I'm encoding the message in "UTF-8" and I've been told that the CCSID I'm using to send the message is 850 instead of 1208 (the one belonging to UTF-8).

To run the MQ manager, I'm using "pymqi" Python library in Client Mode. This is the MQManager class I use to send messages to the queue and get the response:

class MQManager:
    def __init__(self):
        self.queue_manager = config.queue_manager
        self.channel = config.channel
        self.port = config.port
        self.host = config.host
        self.conn_info = config.conn_info
        self.queue_request_name = config.queue_request_name
        self.queue_response_name = config.queue_response_name

        cd = pymqi.CD()
        cd.ChannelName = self.channel
        cd.ConnectionName = self.conn_info
        cd.ChannelType = pymqi.CMQC.MQCHT_CLNTCONN
        cd.TransportType = pymqi.CMQC.MQXPT_TCP

        self.qmgr = pymqi.QueueManager(None)
        self.qmgr.connect_with_options(self.queue_manager, opts=pymqi.CMQC.MQCNO_HANDLE_SHARE_NO_BLOCK, cd=cd)

    def send_message(self, str_xml_message):
        # set message descriptor
        request_md = pymqi.MD()
        request_md.ReplyToQ = self.queue_response_name
        request_md.Format = pymqi.CMQC.MQFMT_STRING

        queue_request = pymqi.Queue(self.qmgr, self.queue_request_name)
        queue_request.put(str_xml_message.encode("UTF-8"), request_md)
        queue_request.close()

        # Set up message descriptor for get.
        response_md = pymqi.MD()
        response_md['CorrelId'] = request_md['MsgId']

        gmo = pymqi.GMO()
        gmo.Options = pymqi.CMQC.MQGMO_WAIT | pymqi.CMQC.MQGMO_FAIL_IF_QUIESCING
        gmo.WaitInterval = 5000  # 5 seconds

        queue_response = pymqi.Queue(self.qmgr, self.queue_response_name)
        message = queue_response.get_no_rfh2(None, response_md, gmo)
        queue_response.close()

        return str(message)


    def close(self):
        self.qmgr.disconnect()

I wonder how can I define the MQ Manager's CCSID value and hopefully solve the codepage mismatch.

Thank you!


Solution

  • In your code you create a default message descriptor for the message you send in this line of code:

    request_md = pymqi.MD()
    

    By default pymqi (like the underlying IBM MQ C libraries) will set the message descriptor CodedCharSetId to the value CMQC.MQCCSI_Q_MGR.

    This can be seen in the source:

    ['CodedCharSetId', CMQC.MQCCSI_Q_MGR, MQLONG_TYPE],
    

    The IBM MQ v9.0 KC page Reference > Developing applications reference > MQI applications reference > Data types used in the MQI > MQMD - Message descriptor > Fields for MQMD > CodedCharSetId (MQLONG) describes how the client handles this:

    For client applications, MQCCSI_Q_MGR is filled in, based on the locale of the client rather than the one on the queue manager.


    The IBM MQ Troubleshooting document What CCSID is used by default for WebSphere MQ client messages explains this in a slightly different way:

    A MQ client sets the MQCCSI_Q_MGR value based on the environment in which the client application is running.


    Based on the 850 CCSID I would guess you are running on a Windows OS that is not in the United States (which commonly uses CCSID 437).


    You have a few options to override this:

    1. You can programmatically override the pymqi MQMD default value like this:

      request_md.CodedCharSetId = 1208
      
    2. Set the env variable MQCCSID to the value you want (in your case 1208). This must be set before you connect to mq. This is documented in the IBM MQ v9.0 KC page Developing applications > Developing MQI applications with IBM MQ > Writing client procedural applications > Using the MQI in a client application > Choosing client or server CCSID.

      The example below is for Windows:

      SET MQCCSID=1208
      
    3. In the mqclient.ini you can set the CCSID=number under the CHANNELS stanza. This is documented in the IBM MQ v9.0 KC page Configuring > Configuring connections between the server and client > Configuring a client using a configuration file > CHANNELS stanza of the client configuration file. For example:

      CHANNELS:
         CCSID=1208