How to create durable subscription to ibm mq amqp topic from java program?

你。 提交于 2021-01-20 12:36:28

问题


We have programmatically created subscriber to IBM MQ AMQP TOPIC with createDurableSubscriber by providing clientId and subscriber name.

We start the program so it subscribes to TOPIC and stop the program. Then send the msgs to topic and again start the receiver program again but we cannot receive the msgs sent and loose the messages which should not happen in case of durable subscription..

We can see amqp topic and its durable subscription when subscriber is connected using mqsc commands DISPLAY TOPIC, DISPLAY TPSTATUS, DISPLAY TPSTATUS SUB, DISPLAY SUB SUBID but not when subscriber program is stopped. We have defined attribute DEFPSIST(YES) and client(producer to topic) is sending persistent messages.

Where are the messages gone as we cannot see messages in durable queues of subscriber? Does it depends on expiry attribute?

Output of DISPLAY SUB SUBID for our subscriber when it is connected.

AMQ8096: WebSphere MQ subscription inquired.


SUBID("hex sub id")
   SUB(:private:CLINET01:TOPIC01)            TOPICSTR(TOPIC01)
   TOPICOBJ(SYSTEM.BASE.TOPIC)             DISTYPE(RESOLVED)
   DEST(SYSTEM.MANAGED.DURABLE.5F6B5C2524FB9AED)
   DESTQMGR(qm.name)                   PUBAPPID( )
   SELECTOR( )                             SELTYPE(NONE)
   USERDATA(010)
   PUBACCT(***************************************************)
   DESTCORL(***************************************************)
   DESTCLAS(MANAGED)                       DURABLE(YES)
   EXPIRY(0)                               PSPROP(MSGPROP)
   PUBPRTY(ASPUB)                          REQONLY(NO)
   SUBSCOPE(ALL)                           SUBLEVEL(1)
   SUBTYPE(API)                            VARUSER(FIXED)
   WSCHEMA(TOPIC)                          SUBUSER(mqm)
   CRDATE(2020-09-28)                      CRTIME(04:14:09)
   ALTDATE(2020-09-28)                     ALTTIME(04:14:09)

Subscriber id has private(not sure why) and client id but not subscriber name which is sub4

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Topic;
import javax.jms.Queue;

import javax.jms.Session;
import javax.jms.TextMessage;
import java.lang.String;
import javax.jms.Destination;
import javax.naming.Context;
import org.apache.qpid.jms.JmsConnectionFactory;
import javax.jms.DeliveryMode;
import javax.naming.InitialContext;
import javax.jms.Message;

public class AMQPQueueExample1 implements Runnable  {
private static final int DELIVERY_MODE = DeliveryMode.PERSISTENT;

public void run(){
try{
 Connection connection = null;
 Context context = new InitialContext();
 ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("myFactoryLookup");
 connection = connectionFactory.createConnection();
 connection.setClientID("123");//("WHATS_MY_PURPOSE3"); // Why do we need clientID while publishing the TOPIC from consumer / publisher
 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 Topic priceTopic = (Topic) context.lookup("myTopicLookup1");
 MessageConsumer subscriber1 = session.createDurableSubscriber(priceTopic,"sub420"); //"sub3");
System.out.println("TOPIC "+priceTopic);

connection.start();
while(true){
TextMessage   message1 = (TextMessage) subscriber1.receive(1000);
if(message1!=null)
           System.out.println("Subscriber 1 received : " + message1.getText());


}
}catch(Exception e){
e.printStackTrace();
}
}

 public static void main(String[] args)  {

AMQPQueueExample1 amp=new AMQPQueueExample1();
 Thread thread = new Thread(amp);
thread.start();


 }
}

Values are taken from jndi.properties file for context factory and provider url.


回答1:


It looks from the comments like you're using MQ 8.0.0.5? If that's the case then Apache Qpid JMS clients aren't supported with that version of MQ. I believe with that version a very basic non-durable subscribe might work, but any other JMS methods are unlikely to.

I suspect what is happening is the AMQP 1.0 flows from Qpid JMS aren't fully understood by that version of MQ, so the expiry of the subscription is being set to 0 rather than unlimited.

MQ 9.2 added support for more of the JMS 2.0 spec - although not every JMS feature. There is more information about the methods which are supported here:

https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.2.0/com.ibm.mq.dev.doc/q125050_.htm

Creating durable subscribers and/or consumers should work as you expect.




回答2:


An article from Matthew Whitehead "MQ Light messaging from Microsoft®.NET™ (Part 4)" states the following:

AMQP channels don’t support setting an unlimited expiry time for MQ Light subscriptions. While it is possible to create subscriptions that have a very long time-to-live, it isn’t possible to create subscriptions to exist forever.

If you wish to create subscriptions that never expire you can do so by creating an MQ administered subscription and having MQ Light clients join and leave the subscription. This can also help to ensure that any messages published to a topic before the first subscribers have connected, aren’t lost completely. Read my previous article on joining MQ Light clients to administered subscriptions.

Related AMQP Fields

To provide the expiry capabilities described above MQ Light uses 2 features of AMQP 1.0:

  • Source Timeout
  • Source Expiry Policy

The source timeout is used to specify the time in seconds that the subscription will expire.

The source expiry policy is used to determine what causes the expiry timer to begin. MQ AMQP channels only support an expiry policy of link-detach, which means the timer starts as soon as the last link detaches from the subscription.


I searched and couldn't find a reference on how to set Source Timeout or Source Expiry Policy in Apache QPID, but the linked blog references setting expiry via a administratively defined subscription. Based on the info in your question I think you can just define something like this ahead of time. I have not specified EXPIRY because this will pick up EXPIRY(UNLIMITED) from SYSTEM.DEFAULT.SUB:

DEFINE SUB(':private:CLINET01:TOPIC01') TOPICOBJ(SYSTEM.BASE.TOPIC) TOPICSTR('TOPIC01') DESTCLAS(MANAGED)

When you then connect your AMQP subscriber it will resume this existing subscription with the expiry set to UNLIMITED.



来源:https://stackoverflow.com/questions/64095699/how-to-create-durable-subscription-to-ibm-mq-amqp-topic-from-java-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!