Original Message:
Sent: Fri May 12, 2023 11:11 AM
From: Martin Evans
Subject: How to set timeToLive on JMS producer globally via com.ibm.mq.allclient driver?
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
Original Message:
Sent: Thu May 04, 2023 02:17 AM
From: metalpalo
Subject: How to set timeToLive on JMS producer globally via com.ibm.mq.allclient driver?
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