MQ

 View Only
Expand all | Collapse all

How to set timeToLive on JMS producer globally via com.ibm.mq.allclient driver?

  • 1.  How to set timeToLive on JMS producer globally via com.ibm.mq.allclient driver?

    Posted Thu May 04, 2023 11:14 AM
    Edited by Kristen Park Thu May 11, 2023 09:43 AM

    Hi All,

    At first I apologize if my message is on incorrect group.

    Im developing spring application sending messages to IBM MQ server(version is irrelevant I think). 
    For this purpose application has maven dependency library "com.ibm.mq.allclient:9.2.3.0"
    I've tried also newest and also older one but no effect.

    Within the application manually created JmsTemplate is constructed with available ConnectionFactory bean.

    ConnectionFactory bean is defined something like this in one configuration class:

    @Bean
        public ConnectionFactory ibmConnectionFactory(IbmConnectorProperties connectorProperties)
            throws JMSException {
          //IbmConnectorProperties is my class with properties neccesary for connection
          MQConnectionFactory factory = new MQConnectionFactory();
          factory.setHostName(connectorProperties.getHostname());
          factory.setPort(connectorProperties.getPort());
          factory.setQueueManager(connectorProperties.getQueueManager());
          factory.setChannel(connectorProperties.getChannel());
          factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
          factory.setMQConnectionOptions(MQConstants.MQPMO_NONE);
    
          //property messageExpiryTime contains value in seconds
          if (connectorProperties.getMessageExpiryTime() != null) {
            factory.setLongProperty(CommonConstants.TIME_TO_LIVE,
                connectorProperties.getMessageExpiryTime().getSeconds() * 1000);
    
            //docs told something that 10th of seconds but I'm focusing on timeToLive
            factory.setLongProperty(WMQConstants.WMQ_EXPIRY,
                connectorProperties.getMessageExpiryTime().getSeconds() * 1000);
          }
          return factory;
        }


    When I call jmsTemplate via execute method it automatically provides session(MQSession) and producer(MQMessageProvider) and then call producer.send(message). My chunk of code with jmsTemplate's usage:

    private void send(Message message) {
            jmsTemplate.execute(
                (session, messageProducer) -> {
                  try {
                    //I would like to avoid manually set timeToLive here(commented line),
                    //I dont have access to properties from connectionFactory, also cast to MQSession and load it from there not acceptable
                    //messageProducer.setTimeToLive(10000); //it sets timeToLive long property in map and expiration works well on IBM server
                    messageProducer.send(message);
                  } finally {
                    //just log message
                  }
                  return null;
                });
      }


    The MQMessageProvider contains delegate JmsMessageProducerImpl(concretely JmsQueueSenderImpl).
    I've debuged construction of whole chain and found that JmsMessageProducerImpl disposes of properties(some clone) overtaken from connection factory.
    But in the middle of constructor method following properties are set to default values: deliveryMode, priority, timeToLive and so on:

    this.setIntProperty("deliveryMode", 2);
    this.setIntProperty("priority", 4);
    this.setLongProperty("timeToLive", 0L);
    this.setLongProperty("deliveryDelay", 0L);


    When looking at decompiled methods getTimeToLive|setTimeToLive I see that they read/write long property "timeToLive" from/into internal properties(map).

    So my question is if possible to set this property globally via connectionFactory construction? 
    I would like to avoid explicit call setTimeToLive method on producer before send or call another overloaded send method with timeToLive parameter. 
    As I mentioned I dont have access to concrete MQ classes there, I would like to keep it abstract and use possibilities of your driver.

    Maybe another question is how is possible to set expiry destination property. When debugging I see that destination has also timeToLive property with higher priority that one from producer.

    Can somebody help me?

    Thanks
    brmetalpalo



  • 2.  RE: How to set timeToLive on JMS producer globally via com.ibm.mq.allclient driver?

    Posted Fri May 12, 2023 11:11 AM
    Edited by Martin Evans Fri May 12, 2023 11:12 AM

    Hi,

    An alternative to setting on the client side could be to use CAPEXPRY on the queue manager, see,  https://www.ibm.com/docs/en/ibm-mq/9.3?topic=mqmd-enforcing-lower-expiration-times



    ------------------------------
    Regards,

    Martin Evans
    IBM MQ Technical Product Manager
    ------------------------------



  • 3.  RE: How to set timeToLive on JMS producer globally via com.ibm.mq.allclient driver?

    Posted Tue May 16, 2023 07:16 AM

    Hi, 
    thanks for hint.

    It seems like administrator's task right? But we would like avoid any management on IBM server.
    For this moment we will use following format for destination's name accross all queues in client application:  queue:///QNAME?expiry=xyz

    brmetalpalo



    ------------------------------
    metalpalo
    ------------------------------