WMQ主题字符串和JMS

WMQ主题字符串和JMS,jms,Jms,我在Windows 2012 Server(A)上使用WMQ 7.5。创建一个名为“价格”的主题,使用不同的主题字符串(“价格/水果/苹果”、“价格/蔬菜/土豆”和“价格/蔬菜/土豆”)进行订阅,以匹配主题树,并为这些订阅创建队列 使用服务器A上的WMQ Explorer,我可以测试和验证我的主题、订阅和队列是否正常工作。为了进行测试,我运行testpublication选项并提供一个主题字符串和一条消息 例如,如果我使用主题字符串“Prices/Fruit/Apples”,则发布的消息将按预期

我在Windows 2012 Server(A)上使用WMQ 7.5。创建一个名为“价格”的主题,使用不同的主题字符串(“价格/水果/苹果”、“价格/蔬菜/土豆”和“价格/蔬菜/土豆”)进行订阅,以匹配主题树,并为这些订阅创建队列

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

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

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

我的发布服务器位于另一台Windows 2012服务器(B)上。这是一个独立的JavaSE应用程序,使用JMS接口。WMQClient已安装在此服务器上。我已经使用JMSAdmin实用程序创建了受管理的TopicConnectionFactory和Topic对象。我将主题管理对象的名称设置为“Prices”

首先,JMS中没有设置主题字符串的方法。IBMdoc指出主题字符串是IBM的一个特性,不在JMS中涵盖。我希望能够在消息对象上设置JMSProperty,以便在消息的头部分向服务器显示主题字符串。常规WMQ类可以做到这一点,但JMS不行

第二,有两种变通办法,这两种办法我都不能接受

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

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

正如我所说的,我认为消息对象头应该将主题字符串信息传递给服务器。这将是一个可接受的解决办法

下面是一些代码,可能会澄清我在出版商中所做的事情

TopicConnectionFactory tcf = (TopicConnectionFactory)context.lookup("TCF"); //Below Topic t is coming from JNDI which is a MQTopic with Name "Prices" Topic t = (Topic)context.lookup("TPrices"); //Below Topic tFruitPrices is coming //from JNDI which is a MQTopic with Name "Prices/Fruit/Apples" Topic tFruitPrices = (Topic)context.lookup("TFruitPrices"); //Below Topic tIBM uses IBM classes directly to create a Topic object Topic tIBM = new MQTopic("Prices/Vegetable/Potatoes"); TopicConnection tc = tcf.createTopicConnection(); TopicSession s = tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); //Below I can choose different topics such as t, tFruitPrices or tIBM to //have the message delivered to different subscriptions TopicPublisher tp = s.createPublisher(tIBM); Message m = s.createTextMessage("From the MyEclipsePublisher"); tp.publish(m); tp.close(); s.close(); tc.close(); TopicConnectionFactory tcf=(TopicConnectionFactory)context.lookup(“tcf”); //下面的主题t来自JNDI,它是一个名为“Prices”的MQTopic topict=(Topic)context.lookup(“TPrices”); //下面的主题是水果价格 //来自JNDI,它是一个名为“价格/水果/苹果”的MQTopic Topic tFruitPrices=(Topic)context.lookup(“tFruitPrices”); //下面的主题tIBM使用IBM类直接创建主题对象 Topic tIBM=新的MQTopic(“价格/蔬菜/土豆”); TopicConnection tc=tcf.createTopicConnection(); TopicSession s=tc.createTopicSession(假,Session.AUTO_确认); //在下面,我可以选择不同的主题,如t、tFruitPrices或tIBM //将邮件传递到不同的订阅 TopicPublisher tp=s.createPublisher(tIBM); 消息m=s.createTextMessage(“来自MyEclipsePublisher”); tp.发布(m); tp.close(); s、 close(); tc.close(); 有人知道在这个问题上是否有可接受的解决方法吗

谢谢,
-Dogan Atay

您看过WMQ附带的JMS发布/订阅示例了吗。我在这里粘贴了一个代码段,它通过编程创建了一个主题,并使用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);

我不得不使用变通方法1。和你描述的问题完全一样。现在是你面临同样问题的一年之后。看来没有别的办法了。看看萨西回答下面的评论。他的答案确实有用!事实上,萨西的答案确实有效。您需要获取连接工厂,创建会话,并在会话上调用createTopic(“topic://”)。从那里使用目的地,然后发布消息。这将JMSDestination设置为主题字符串,MQ将其路由到正确的队列。调用session.createTopic()时,它实际上并不会在队列管理器上创建新主题,而是通过设置主题字符串来获取该主题的句柄。可以说,这是IBM的一个糟糕的解决方案。它不是直观的,JMS是一个API规范,基本上它告诉了JMS API应该做什么以及它的签名。它没有指定JMS提供者应该如何实现API。它将实现细节留给提供者。因此,IBM以自己的方式实现了JMS API。其他JMS提供程序可能以不同的方式实现。