How to determine the value of `MaxMsgLength` of queue - ibm-mq

I am trying to write simple string message into a queue. The MaxMsgLength property of queue is set as 4 kb. The message has 2700 characters and when I try to put into queue I am getting 2030 (07EE) (RC2030): MQRC_MSG_TOO_BIG_FOR_Q exception. I am not doing any special kind of encoding and hence whatever is default for Windows should be used.
I want to know how to determine the value that I should give in MaxMsgLength property. How to calculate that.

Please remember that the MaxMsgLength as specified in the queue definition includes not just the payload, but also the message header and any properties that you set. If you check the Infocenter MQ_* (String Lengths) page and look for MQ_MSG_HEADER_LENGTH you will see that the MQMD alone is 4000 bytes. So if you set the MaxMsgLength of the queue to 4k, the largest payload you can have is 96 bytes. If the queue in question is a transmission queue, you need the queue size plus the size of the MQXQH transmission queue header.
To specifically answer the question in the title of the post, you can find the MaxMsgLength in two ways. Visually, by displaying the queue attributes. Programmatically, add "Inquire" to the open options when opening the queue and use the MQInq API call. Then add the total of the MQMD, any properties that you add (including the XML structures that contain them but are not returned in the API calls that manipulate them) plus any headers such as RFH2 (if the queues are set to use that instead of native properties), MQXQH, MQDLQ, etc.

Not sure what language you are using in your application. Assuming it is C, check BufferLength parameter value you have specified on the MQPUT call.
This IBM MQ InfoCenter link explains the case where you can run into 2030 error and possible remedies.

Related

IBMMQ, under what scenario will MQMD.MsgType=1 be interpreted as MQMT_SYSTEM_FIRST instead of MQMT_REQUEST

We are using JmsTemplate to send messages to an IBM MQ's local queue. We set MQMD property MsgType to 1, but when viewing the message header from the queue, the value is interpreted as MQMT_SYSTEM_FIRST instead of MQMT_REQUEST. Why is that? Is this the reason why the other party's system cannot return the reply message?
We are doing debugging with another system. According to their feedback, they checked our message header in the queue like this.
enter image description here
But based on past experience, our message should look like this (Please focus only on the MsgType field).
enter image description here
And there is no clue as to why these two different situations occur. Their values are both 1, but MQMT_SYSTEM_FIRST and MQMT_REQUEST are displayed respectively.
I suspect this is just a flaw in whatever you use to view the header in that it does not realize MQMT_SYSTEM_FIRST is never 'set', it is just a range identifier.
What are you using to view the header?
This question is really a duplicate of IBM MQMD header how to distinguish

Apache.NMS.AMQP setting prefetch size

I am using Apache.NMS.AMQP (v1.8.0) to connect to AWS managed ActiveMQ (v5.15.9) broker but am having problems with setting prefetch size for connection/consumer/destination (couldn't set custom value on either of them).
While digging through source code I've found that default prefetch value (DEFAULT_CREDITS) is set to 200.
To test this behavior I've written test that enqueues 220 messages on a single queue, creates two consumers and then consumes messages. The result was, as expected, that first consumer dequeued 200 messages and second dequeued 20 messages.
After that I was looking for a way to set prefetch size on my consumer without any success since LinkCredit property of ConsumerInfo class is readonly.
Since my usecase requires me to set one prefetch size for connection that is what I've tried next according to this documentation page, but no success. This are URLs that I've tried:
amqps://*my-broker-url*.amazonaws.com:5671?transport.prefetch=50
amqps://*my-broker-url*.amazonaws.com:5671?jms.prefetchPolicy.all=50
amqps://*my-broker-url*.amazonaws.com:5671?jms.prefetchPolicy.queuePrefetch=50
After trying everything stated above I've tried setting prefetch for my queue destinations by appending
?consumer.prefetchSize=50 to queue name. Resulting in something like this:
queue://TestQueue?consumer.prefetchSize=50
All of above attempts resulted with effective prefetch size of 200 (determined through test described above).
Is there any way to set custom prefetch size per connection when connecting to broker using AMQP? Is there any other way to configure broker than through query parameters stated on this documentation page?
From a quick read of the code there isn't any means of setting the consumer link credit in the NMS.AMQP client implementation at this time. This seems to be something that would need to be added as it currently seems to just use a default value to supply to the AmqpNetLite receiver link for auto refill.
Their issue reporter is here.

To identify the xsd of xml message which is received from MQ

In IBM MQ, I have a requirement where I can get many types of xml from the queue. The xml messages will be conformed to already specified xsd (there are say, 5 xsd - which means I can get 5 different xml). When I get the message from queue, I would like to know the type of xml (if its xsd1 or xsd2 or so on)
The reason why I would want to know is, I am using a JaxB interface with SAX implementation, for which I need to give the java object corresponding to the xml as parameter. So I have to know which xsd the input and is and assign the parameter correspondingly.
The options I have is to set a property in the header to the message, but the party who is dropping the message into MQ is not ready.
What other options do I have? Can I get the file name (of xml) from the mq and find the xsd based on the name of the file? Or do I have to do I sax parsing and identify the root tag and derive the xsd type? Any other better option anybody has in mind?
Think of MQ like the Post Office. When you get a letter, the post office doesn't mess with anything on the inside (the payload) and if it changes the outside, it only changes routing information. If you want to sort incoming mail to different recipients, whoever is sending it has to put the data against which the sort criteria operate on the outside of the envelope. If that doesn't work, you must open the envelope and look for the recipient name, department, or whatever on the papers inside.
Your MQ message is that envelope. The sort criteria can be different queue names, a property of the message, a property of the message header, or something in the payload. But unless the sender explicitly sets the destination queue name based on the selection criteria, or sets the message or header property, your only option is to inspect the payload and figure it out.
If you have to inspect the payload, this is a perfect scenario for IBM Integration Broker. But you can also write an application to perform this function. Very often this is performed by a Dispatch app which gets the message, figures out where it goes, then puts it onto another queue and COMMITs the GET and PUT operations. But if the dispatch app must parse the XML to determine the correct queue, the message has to be parsed twice - once by the dispatcher, once by the receiving app.
I think you can do:
Does the incoming message has the file name at the beginning of the message body? In that case, after receiving the message your application can read first few bytes to get the file name. Based on the file name, application can use appropriate Xsd and pass the entire message body.

ActiveMQ LIFO ordering?

Is there any option to change queue order without using out of box "Resequencer"? Maybe it can be done using JMS client to get last message in queue instead of first?
I think that you should give more info about what you're trying to achieve...
Anyway if you read the specs of some JMS implementation like MQ you'll see that the FIFO order is not guaranteed at 100%.
That means that if you relay on the order of the messages received, you can get easily in trouble.
It's good practice to add a progressive number to the message header and use it to handle the messages as you please. If you adopt this solution you have 2 options to achieve your goal:
1) modify the receiver business logic to check the the header of the message;
2) (probably the cleaner approach if you're using MQ) use something called MESSAGE SELECTOR.
Message Selectors allow content based retrieval of specific messages using SQL92-query functions. MQ spec states:
The JMS message provides a facility to provide user-defined metadata
to the JMS message header (outside the actual body of the message).
JMS programs can take advantage of this facility to select a subset
of messages based on a selection criteria or, in other words, a JMS
client can choose only those messages that it is interested in.
Here some more info about the implementation of the two solutions...
The property that you're probably interested in and that you should set before sending the message is JMSCorrelationID that will be set to 1 for the first message, 2 for the second one and so on.
1) Since you're more interested in the message selector, you can skip to the next bullet. Anyway just for reference, if you decide to adopt the solution 1 you can find some good reference in:
http://activemq.apache.org/maven/apidocs/org/apache/activemq/ActiveMQQueueBrowser.html
2) Message Selector.
Your message selector will be an sql string like: JMSCorrelationID = max(JMSCorrelationID)
If you wanna implement a message selector in java the syntax is:
MessageConsumer consumer = session.createConsumer(destination, messageSelectorString, true);
ActiveMQObjectMessage objMsg = (ActiveMQObjectMessage) consumer.receiveNoWait();

Equivalent of org.hornetq.api.core.client.ClientMessage.setBodyInputStream in IBM MQSeries

In the following JBoss/HornetQ user manual page you can see how HornetQ provides a mechanism for streaming data to a Message for a Queue using a java.io.InputStream. A JMS version of the same code is given. Has anyone come across an equivalent using IBM MQSeries / WebsphereMQ?
Say I have a large amount of data to place in the JMS Message which to me is just a stream of bytes. In the Hornet example, the stream is only read when the message is sent, so if it is, say a FileInputStream, then we only need enough memory to buffer a chunk of the bytes. I can use a javax.jms.BytesMessage to send in chunks of bytes and use the BytesMessage to buffer them. The problem with this is that the IBM implementation of BytesMessage (com.ibm.msg.client.jms.internal.JmsBytesMessageImpl) has to cache them until the Message is sent and if that is a large amount of data it is a problem. Worse it appears that although I am only sending bytes, the IBM implementation appears to keep duplicate copies, one in a BytesArrayOutputStream the other in a DataOutputStream.
In WebSphere MQ the closest thing to what you describe is a reference message. The method described in the Infocenter requires custom programming of channel exits to grab the filesystem object and put it into a message before it is transmitted over the channel. A complementary exit on the remote side saves the payload to a file and puts a reference to the file in the message that is returned to the app.
We also have programs in WMQ that take STDIN or a pipe at one end and put messages to a queue on the other end. A pair of these can act as a pipe through which line-oriented ASCII data flows between processes on separate machines. However, there's no JMS implementation of this and it doesn't work too well for binary data.
In WMQ, we have concept of Group and Segment.
Segmentation is supported in all OS except Z/OS.
Check for details here Segmentation In WMQ
Make use of GroupId, MsgSeqNumber, and Offset while putting the message.
While getting the message if you give MQGMO_COMPLETE_MSG in GMO, then all segments are joined automatically according to the MsgSeqNumber and
you will get a single message on the recieving application with a
single GET.

Resources