【问题标题】:Mainframe MQ to Standalone JMS in EBCDIC大型机 MQ 到 EBCDIC 中的独立 JMS
【发布时间】:2020-05-06 19:26:05
【问题描述】:

我正在尝试从 Java 应用程序浏览大型机 IBM MQ 队列中的消息(EBCDIC 消息)。我需要浏览消息,而不是消费它们。代码如下:

JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();

// Set properties
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, host);
cf.setIntProperty(WMQConstants.WMQ_PORT, port);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, qmgr);
cf.setIntProperty(WMQConstants.WMQ_RECEIVE_CONVERSION, WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);

QueueBrowser browser = context.createBrowser(context.createQueue("queue:///" + queueName  + "?targetClient=1"));
Enumeration enumeration = browser.getEnumeration();

while (enumeration.hasMoreElements()) {
    TextMessage messageInTheQueue = (TextMessage) enumeration.nextElement();
    System.out.println(messageInTheQueue);
    nbRecords++;
}

System.out.println() 的结果如下:

  JMSMessage class: jms_text
  JMSType:          null
  JMSDeliveryMode:  2
  JMSMessageID:     ID:c1d4d840d4d8e3c1e2f24040404040405e2432bd21aa1b02
  JMSTimestamp:     1579537307450
  JMSRedelivered:   false
    JMSXAppID:  
    JMSXDeliveryCount: 1
    JMSXUserID:    
    JMS_IBM_Character_Set: IBM037
    JMS_IBM_Encoding: 273
    JMS_IBM_Format: MQSTR   
    JMS_IBM_MsgType: 8
    JMS_IBM_PutApplType: 8
    JMS_IBM_PutDate: 20200120
    JMS_IBM_PutTime: 16214745
ÍÍÑÀ ...

我想将此 EBCDIC 消息 ÍÍÑÀ ... 转换为可读的 (ASCII)。

我尝试将 enumeration.nextElement() 转换为 JMSByteMessage 但得到了这个异常:

class com.ibm.msg.client.jms.internal.JmsTextMessageImpl cannot be cast to class com.ibm.jms.JMSBytesMessage

我该怎么做?

解决方案: 使用 Java 的 MQ 类 而不是 Java 的 MQ JMS 类:

byte[] strData = new byte[theMessage.getMessageLength()];
theMessage.readFully(strData, 0, theMessage.getMessageLength());

这里有一些例子:https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q030840_.htm

【问题讨论】:

  • 你试过没有cf.setIntProperty(WMQConstants.WMQ_RECEIVE_CONVERSION, WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);吗?请注意,targetClient 与生产者而非接收者相关,它可能对您设置的上下文没有影响。
  • 您是否直接连接到大型机?我相信如果您不设置 CCSID,CCSID 将默认为队列管理器的 CCSID 以用于WMQ_RECEIVE_CONVERSION_QMGR。如果未设置WMQ_RECEIVE_CONVERSION,则默认应由IBM MQ 类JMS 进行转换,此转换的CCSID 目标通常为1208,即UTF-8。我认为如果你不设置WMQ_RECEIVE_CONVERSION,你应该得到你可以阅读的文本,或者将你的CCSID设置为1208,看看队列管理器是否可以转换它。
  • 我尝试了设置和不设置WMQ_RECEIVE_CONVERSION,但结果是一样的,仍然没有可读的'UTF-8'。我认为 enumeration.nextElement(); 只返回文本 JMSTextMessage 。根据:ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/… 我需要一个JMSBytesMessage,这样我才能执行转换。
  • 如果您使用的是 IBM MQ jar 文件是什么版本?
  • 我终于切换到 com.ibm.mq 罐子,而不是 com.ibm.msg.client.jms 和 com.ibm.jms。在这种情况下,不再有 JMS 层。这是我使用的代码:ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/… 基本上使用这个解决方案,我能够获得一个字节数组并转换为字符串:byte[] strData = new byte[theMessage.getMessageLength()]; theMessage.readFully(strData, 0, theMessage.getMessageLength()); 我用这个解决方案编辑了原始帖子。

标签: jms ibm-mq ebcdic


【解决方案1】:

关于 OP 的原始代码,以下文档说明接收转换和 CCSID 仅对 MQDestination 类有效:https://www.ibm.com/docs/en/ibm-mq/9.2?topic=reference-properties-mq-classes-jms-objects

因此,可以使用 IBM MQ Classes for JMS 来完成。你只需要以一种更迂回的方式来做。

为了让 QueueBrowser 读取 EBCDIC 格式的消息,您需要将 JMS Queue 转换为 MQDestination,然后设置 receiveConversion & receiveCCSID,然后在创建浏览器时,将 MQDestination 转换回常规 JMS Queue。像这样:

JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();

// Set properties
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, host);
cf.setIntProperty(WMQConstants.WMQ_PORT, port);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, qmgr);

JMSContext context = cf.createContext();
MQDestination targetQueue = (MQDestination) context.createQueue("queue:///" + queueName)
targetQueue.setReceiveCCSID(WMQConstants.CCSID_UTF8);
targetQueue.setReceiveConversion(WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);
targetQueue.setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ);
QueueBrowser browser = context.createBrowser((Queue) targetQueue);
Enumeration enumeration = browser.getEnumeration();

while (enumeration.hasMoreElements()) {
    TextMessage messageInTheQueue = (TextMessage) enumeration.nextElement();
    System.out.println(messageInTheQueue);
    nbRecords++;
}

这样做时,您也不需要使用 JMS URI 属性来设置目标客户端,因为 MQDestination 具有所有必要的 getter/setter 来修改本来可以使用 URI 完成的属性负载。

有关 MQDestination 的更多信息,请参阅以下文档:https://www.ibm.com/docs/en/ibm-mq/9.2?topic=jms-mqdestination

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-11
    • 2014-07-05
    • 2014-05-08
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    相关资源
    最近更新 更多