【问题标题】:WMQ Topic String and JMSWMQ 主题字符串和 JMS
【发布时间】:2014-06-26 10:30:24
【问题描述】:

我在 Windows 2012 Server(A) 上使用 WMQ 7.5。创建了一个名为“Prices”的主题,具有不同主题字符串的订阅(“Prices/Fruit/Apples”、“Prices/#/#”和“Prices/Vegetable/Potatoes”)以匹配主题树并为这些订阅创建队列。

使用服务器 A 上的 WMQ Explorer,我可以测试并验证我的主题、订阅和队列是否正常工作。为了进行测试,我运行测试发布选项并提供主题字符串和消息。

例如,如果我使用主题字符串“Prices/Fruit/Apples”,则发布的消息将按预期传递到“Prices/Fruit/Apples”和“Prices/#/#”订阅队列。

问题是如何在使用 JMS 的发布者中以编程方式设置主题字符串。

我的发布者驻留在另一个 Windows 2012 Server(B) 上。这是一个独立的 Java SE 应用程序并使用 JMS 接口。 WMQClient 安装在此服务器上。我使用 JMSAdmin 实用程序创建了受管理的 TopicConnectionFactory 和 Topic 对象。我将主题管理对象的名称设置为“价格”。

首先,JMS 中没有设置主题字符串的方法。 IBM 文档指出主题字符串是 IBM 的一项功能,JMS 中没有涉及。我期待我能够在 Message 对象上设置一个 JMSProperty,以便在消息的标头部分中将主题字符串呈现给服务器。常规 WMQ 类可以做到这一点,但 JMS 不能。

其次,有两种解决方法,我都不能接受。

解决方法 1) 创建受管理的 JNDI 主题对象,其名称与订阅的主题字符串完全相同。如果我有 15 个订阅,我必须创建 15 个 JNDI 主题对象并为适当的订阅选择正确的 JNDI 对象。

解决方法 2) 在创建 JMS 主题对象时不要使用 JNDI。相反,通过使用主题字符串作为名称来实例化 MQTopic 来使用 IBM 的 MQTopic 对象。该解决方案将我的发布者代码直接与 IBM 类相关联,并降低了我的解决方案的可移植性。

正如我所说,我认为 Message 对象头应该携带主题字符串信息到服务器。这将是一个可以接受的解决方案。

下面是一些代码,可以阐明我在发布者中所做的事情。

TopicConnectionFactory tcf = (TopicConnectionFactory)context.lookup("TCF"); //下面的主题 t 来自 JNDI,它是一个名为“价格”的 MQTopic 主题 t = (Topic)context.lookup("TPrices"); //下面的主题 tFruitPrices 来了 //来自 JNDI,它是一个名为“Prices/Fruit/Apples”的 MQTopic 主题 tFruitPrices = (Topic)context.lookup("TFruitPrices"); //Topic下面tIBM直接使用IBM类创建Topic对象 主题 tIBM = new MQTopic("价格/蔬菜/土豆"); TopicConnection tc = tcf.createTopicConnection(); TopicSession s = tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); //下面我可以选择t、tFruitPrices或tIBM等不同的主题来 //将消息传递给不同的订阅 TopicPublisher tp = s.createPublisher(tIBM); Message m = s.createTextMessage("来自 MyEclipsePublisher"); tp.publish(m); tp.close(); s.close(); tc.close();

有人知道这个问题是否有可接受的解决方法吗?

谢谢, -Dogan Atay

【问题讨论】:

  • 我不得不使用解决方法 1。与您描述的问题完全相同。现在是您遇到同样问题的 1 年。看来没有别的办法了。
  • 看看Sashi 回答下的cmets。他的回答确实有效!

标签: jms


【解决方案1】:

您是否查看过随 WMQ 提供的 JMS Pub/Sub 示例。我在这里粘贴一个 sn-p,它以编程方式创建主题并使用 JMS 接口发布消息。具体看一下 .createTopic 调用。

public static void main(String[] args) {

// Variables
Connection connection = null;
Session session = null;
Destination destination = null;
MessageProducer producer = null;
MessageConsumer consumer = null;

try {
  // Create a connection factory
  JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
  JmsConnectionFactory cf = ff.createConnectionFactory();

  // Set the properties
  cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, "localhost");
  cf.setIntProperty(WMQConstants.WMQ_PORT, 1414);
  cf.setStringProperty(WMQConstants.WMQ_CHANNEL, "SYSTEM.DEF.SVRCONN");
  cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
  cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM1");

  // Create JMS objects
  connection = cf.createConnection();
  session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  destination = session.createTopic("topic://foo");
  producer = session.createProducer(destination);
  consumer = session.createConsumer(destination);

  long uniqueNumber = System.currentTimeMillis() % 1000;
  TextMessage message = session.createTextMessage("SimplePubSub: Your lucky number today is "
      + uniqueNumber);

  // Start the connection
  connection.start();

  // And, send the message
  producer.send(message);
  System.out.println("Sent message:\n" + message);

【讨论】:

  • 实际上 Sashi 的回答确实有效。您需要获取连接工厂,创建会话并在会话上调用 createTopic("topic://")。从那里使用目的地,然后发布消息。这将 JMSDestination 设置为主题字符串,并且 MQ 将其​​路由到正确的队列。当调用 session.createTopic() 时,它实际上并没有在队列管理器上创建新主题,只是让您使用主题字符串集来处理该主题。可以这么说,这是 IBM 的一个糟糕的解决方法。它不直观。
  • 嗯,JMS 是一个 API 规范,基本上它告诉 JMS API 应该做什么以及它的签名。它没有指定 JMS 提供者应如何实现 API。它将实现细节留给提供者。因此,IBM 以自己的方式实现了 JMS API。其他 JMS 提供者可能以不同的方式实现。
猜你喜欢
  • 2015-01-01
  • 2014-04-05
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-03
  • 2015-12-13
相关资源
最近更新 更多