IBM MQ Little Gem #45: SubLevel

By Morag Hughson posted Fri February 14, 2020 11:55 PM

This is part of a series of small blog posts which will cover some of the smaller, perhaps less likely to be noticed, features of IBM MQ. Read other posts in this series.

Republish_with_SubLevel.jpgIf you have subscribing applications that need to see a publication before other subscribers, you might find that the SubLevel option is useful for you.

This feature of IBM MQ Pub/Sub was designed for applications that filter out certain publications, or perhaps annotate the contents of the publication message before sending it on for other subscribers to see. It might even be used to implement tiering of subscriptions, delaying the delivery to lower tiered subscribers until the highest tier has had their delivery.

If you have a requirement for a subscription to receive the publication message before everyone else, then this particular subscription should be made at a higher SubLevel than the default. In the code snippets below, I illustrate how this should be done, and there are a few requirements on this code. You can obtain the full sample I created from the link at the end.

If you start making use of non-default SubLevel values, then your application must also re-publish the message for the lower-down subscriptions, or they will never see the message.

MQSUB (SubLevel = 9)
MQGET (message)
MQPUT1(message with PubLevel = 8)

Most subscriptions will use the default value of a SubLevel of 1, which means that they will only see the publication if there are no higher level subscriptions in place. Most publications will be sent using the default value of PubLevel of 9, and will be delivered to all the subscriptions with the highest SubLevel. When only the default values are in use, all subscriptions will be at the same SubLevel and all will see all publications.

If you only have one application that needs to get the message first, it can also be responsible for re-publishing the message downstream.

However, if you have multiple applications that need to subscribe at a SubLevel of 9, only one of them should re-publish the message downstream. In this case, it might be better to have an application whose sole purpose is to subscribe at the higher level and re-publish, while the remaining applications only need to change their SubLevel and nothing else.

  • In order to ensure that the contents of the MQMD of the publication message get passed on to the lower level subscribers:-
    • Use the same MQMD that you used for the MQGET, for the MQPUT as well.
    • Use save and pass context options, if the Origin Context fields are important for downstream subscribers. This means that your application cannot use a managed subscriber queue. However, it is quite likely that your application doesn't care at all about these fields.
      OpenOpts |= MQOO_SAVE_ALL_CONTEXT;
      PutOpts.Options |= MQPMO_PASS_ALL_CONTEXT;
      PutOpts.Context  = hObj;
    • Ensure your subscription requests the publisher's correlation ID, and message priority, if that information is important for downstream subscribers. The requirement on the correlation ID also means that your application cannot use a managed subscriber queue.
      SubDesc.Options = MQSO_CREATE
                      | MQSO_NON_DURABLE
                      | MQSO_SET_CORREL_ID
                      | MQSO_FAIL_IF_QUIESCING;
      memcpy(SubDesc.SubCorrelId, MQCI_NONE, MQ_CORREL_ID_LENGTH);
      SubDesc.PubPriority = MQPRI_PRIORITY_AS_PUBLISHED; /* Default anyway */
  • If retained publications are being used, the MQPMO_RETAIN option must be used on the downstream publish. You can obtain the put options you must use on your publication, by inquiring the MQPubOptions message property from the message you received. Use this value as the basis for your Options on the MQPUT call, and then add in any additional options you need.
    WriteOutput("Message Property MQPubOptions = %8.8X\n", PutOpts.Options);
    PutOpts.Options |= MQPMO_SYNCPOINT
                     | MQPMO_FAIL_IF_QUIESCING;
  • If your subscribing application uses a wildcard in the topic string, you must obtain the full topic string, by inquiring the MQTopicString message property from the message you received, and use that on the downstream publish.
  • The prior two points mean that you must create a message handle, and pass the handle on the MQGET call to be able to obtain these message properties.
    GetOpts.Version   = MQGMO_VERSION_4;      /* Needed for MsgHandle */
    GetOpts.MsgHandle = hMsg;

The full sample is available for you to download and play with. You can use the amqssub and amqspub IBM-supplied samples as the original publisher and the SubLevel of 1 subscriber.

You may also find this Knowledge Center page useful.

The sample application for your perusal is here: subcept.c

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.