This is part of an occasional series of small blog posts where I (Morag) will write about some of the quirks in IBM MQ, in the hope of invoking the response, "Well, I didn't know that!" Read other posts in this series.
IBM MQ V8 Fix Pack 4 (and APAR PI50761 on z/OS) added a feature to allow administrative control of the expiry of messages. Since this was new function introduced in a Fix Pack, it was added using the CUSTOM parameter. In a future release I hope we will see this turned into a 'real' attribute.
This blog post will cover what it is and when to use it, and also, since it is quirky, how to use it. This hope of the author is that this latter part of the blog post will be obsolete in the future, and when that happens, it will be updated to indicate as such.
IBM MQ has the concept of a time to live, or expiry value on messages. This can be found in the Message Descriptor (MQMD) and up until the feature we are describing was added, it was up to the application to set the expiry of its messages.
There are a number of fields in the message, and options on MQ API calls that an application programmer can leave the setting of which up to the administrator. Not all of these the author agrees with (persistence being the most controversial), but many of these are useful, especially to have existing applications make use of new features without any changes since these "As definition" are usually the default. As you can see, there is no such concept as default expiry.
|Field or Option
||Option to use to defer to administrator
||Queue attribute to set the value when deferred
|Properties on MQGET
If you had an application which was not written well, and should be setting an expiry value in its messages but does not, previously your only recourse was to have a friendly chat with the application developer. Now with the introduction of this new feature, you can apply an administrative oversight.
Capping message expiry
With this new feature, you are able to set a maximum value for expiry values in messages. This is not a default expiry setting, but a maximum. So if messages are put with a small expiry value, you cannot increase them, but if messages are put with a large expiry (or unlimited expiry) then you can set the highest value these new messages should take.
Examples are often the best way to explain such things, so here are some examples.
Application does not use expiry
If you have an application that does not use expiry, but the application really should, for example, the messages sent to it are inquiry messages that if it does not process within a certain time become obsolete. The applications sending these message really should set an expiry value. The pain for the administrator is that these messages will unnecessarily queue up for the application when it is not online, when really they could be discarded. Find yourself clearing application queues on the weekend with this logic? Perhaps an administrative intervention would help here.
You can set expiry on any new messages put to this queue by using the following MQSC command.
ALTER QLOCAL(APP.INPUT.QUEUE) CUSTOM('CAPEXPRY(600)')
This command will set the expiry of any new messages to 600 tenths of a second - so this command results in 60 seconds life of any new messages put to the queue. Any messages that were already on the queue prior to you issuing this command are not changed.
Application uses expiry on some messages
With an application that has a mix of messages on a queue, perhaps some use expiry and some don't, you can limit the lifespan of those where the application does not apply expiry, by adding an upper limit. This will add expiry to those messages that are put with none, and reduce the expiry on any messages that are put setting an expiry value. In this case, perhaps you set a value that is equal to or higher than the longest expiry values used by those applications that do put messages with expiry, therefore not causing any changes to those messages.
ALTER QLOCAL(APP.INPUT.QUEUE) CUSTOM('CAPEXPRY(6000)')
This command will set the expiry of any new messages to 6000 tenths of a second - so this command results in 10 minutes life of any new messages put to the queue. Any messages that were already on the queue prior to you issuing this command are not changed.
You have seen some example MQSC commands that show how to use CAPEXPRY. It is quirky because you have to add the parameter as a string on the CUSTOM parameter. Normally, you would have an attribute to set the value in but not in this case.
If you have, or are writing a PCF administrative tool or application that you need to update, you will have to find and use the Custom attribute, which has PCF parameter identifier MQCA_CUSTOM. This is a string attribute, and you will then have to place the same string that you saw in the MQSC examples, into this PCF string parameter, that is "CAPEXPRY(6000)". This is quirky, and also will change if the IBM MQ development team roll this custom parameter into the product as a real attribute.
In the mean time though, here is some example Java code to demonstrate how to set the value of CAPEXPRY using PCF.
request = new PCFMessage(CMQCFC.MQCMD_CHANGE_Q);
responses = agent.send(request);
The Custom attribute
The use of the custom attribute is what makes this particular feature quirky. This was necessary to deliver the feature in the service stream as it originally was - to avoid destabilizing the code base with the addition of new function. When a feature is delivered like this through the service stream, the next MQ development release should roll the feature into IBM MQ and give it a real attribute. For some reason this was not done in V9.0, or in V9.1.
An MQ RFE has been raised to request this be done in a future release, which will make it much easier to use this attribute going forward. Vote for it if you agree. It will mean that anything you have coded to use custom in the interim will need to be changed when this is done.
Other Reading Material
Here are some links to other reading material on this subject.
#mquirks #IBMMQ #ChampionsCorner