MQ

 View Only

Morag's Quirks #5: CAPEXPRY

By Morag Hughson posted Tue May 28, 2019 08:28 PM

  
Morag's
Quirks
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.

UPDATE: For distributed platforms, CAPEXPRY is now a first class queue attribute. For z/OS, use of the CUSTOM attribute is still required.

Message Expiry

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
MQMD.Priority MQPMO_PRIORITY_AS_Q_DEF
MQPMO_PRIORITY_AS_TOPIC_DEF
DEFPRTY
MQMD.Persistence MQPER_PERSISTENCE_AS_Q_DEF
MQPER_PERSISTENCE_AS_TOPIC_DEF
DEFPSIST
Bind Options MQOO_BIND_AS_Q_DEF DEFBIND
Put Response MQPMO_RESPONSE_AS_Q_DEF
MQPMO_RESPONSE_AS_TOPIC_DEF
DEFPRESP
Read Ahead MQOO_READ_AHEAD_AS_Q_DEF
MQSO_READ_AHEAD_AS_Q_DEF
DEFREADA
Sharing MQOO_INPUT_AS_Q_DEF DEFSOPT
Automatic Reconnect MQCNO_RECONNECT_AS_DEF
Properties on MQGET MQGMO_PROPERTIES_AS_Q_DEF PROPCTL

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

Cap_Expiry.jpgWith 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.

Administrative Commands

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);
request.addParameter(CMQC.MQCA_Q_NAME, QName); 
request.addParameter(CMQC.MQIA_Q_TYPE, CMQC.MQQT_LOCAL); 
request.addParameter(CMQC.MQCA_CUSTOM,"CAPEXPRY(6000)");
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.


Morag Hughson is an MQ expert. She spent 18 years in the MQ Devt organisation before taking on her current job writing MQ Technical education courses with MQGem. She also blogs for MQGem. You can connect with her here on IMWUC or on Twitter and LinkedIn.


#mquirks
#IBMMQ
#IBMChampion

0 comments
54 views

Permalink