I am fairly new to MQMessage broker. In my project, I want to send an xml message. Every thing is ok but when message get larger than 500 bytes, My code send broken message to the Queue. what I am doing is
//queueManager has been initialized in the class constructor and connected to a channel.
public MQResponse WriteMsg(string QueueName, string strInputMsg)
{
MQResponse response = new MQResponse();
try
{
queue = queueManager.AccessQueue(QueueName,
MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING );
queueMessage = new MQMessage();
queueMessage.DataOffset = 0;
//queueMessage.MessageLength = 2000000;
queueMessage.ResizeBuffer(6 * strInputMsg.Length);
queueMessage.WriteString(strInputMsg);
queueMessage.Format = MQC.MQFMT_STRING;
queuePutMessageOptions = new MQPutMessageOptions();
queue.Put(queueMessage, queuePutMessageOptions);
response.Message = "Message sent to the queue successfully";
response.Status=MQResponseStatus.WriteSuccessful;
}
catch (MQException MQexp)
{
response.Message = "Exception: " + MQexp.Message;
response.Status=MQResponseStatus.WriteFail;
response.CatchedException=MQexp;
}
catch (Exception exp)
{
response.Message = "Exception: " + exp.Message;
response.Status=MQResponseStatus.WriteFail;
response.CatchedException=exp;
}
return response;
}
I guess queueMessage should be initialized correctly so that we able to send whole message.
First of all how did you determine that the message is broken? Did you try to receive the sent message and compared with the original message or you viewed the message using MQExplorer or some other means. MQExplorer by default displays first 1000 bytes of the message. To view more you need to change the Max data bytes displayed setting in Window/Preferences/Messages panel.
WebSphere MQ can handle messages of size as large as 100 MB.
Regarding your code snippet above: The few lines of code is enough to build and send a message.
queueMessage = new MQMessage();
queueMessage.Format = MQC.MQFMT_STRING;
queueMessage.WriteString(strInputMsg);
queuePutMessageOptions = new MQPutMessageOptions();
queue.Put(queueMessage, queuePutMessageOptions);
Related
When we compare QueueBrowser with MessageListener, QueueBrowser is very slow.
QueueBrowser is taking approx 1 min to process 100 messages where as consumer is processing ~840 messages.
This mush difference is expected? can you please suggest if anything needs to be changed in the below code:
queueEnum = queueBrowserIn.GetEnumerator();
while (true)
{
if (queueEnum.MoveNext())
{
messageCount++;
LogWrite($"Message No - {messageCount} - Method: ProcessNewMesage" + DateTime.Now);
IBytesMessage bytesMessage = queueEnum.Current as IBytesMessage;
if (bytesMessage != null)
{
byte[] arrayMessage = new byte[bytesMessage.BodyLength];
bytesMessage.ReadBytes(arrayMessage);
string message = System.Text.Encoding.Default.GetString(arrayMessage);
}
}
}
I am wring custom java code to read messages from Websphere MQ (version 8) and read all the headers from the MQ message.
When I use the MQHeaderList to parse all the headers the list size is 0:
MQMessage message = new MQMessage();
queue.get(message, getOptions);
DataInput in = new DataInputStream (new ByteArrayInputStream (b));
MQHeaderList headersfoundlist = null;
headersfoundlist = new MQHeaderList (in);
System.out.println("headersfoundlist size: " + headersfoundlist.size());
However, I read only a specific MQRFH2 it works
MQMessage message = new MQMessage();
queue.get(message, getOptions);
DataInput in = new DataInputStream (new ByteArrayInputStream (b));
MQRFH2 rfh2 = new MQRFH2(in);
Element usrfolder = rfh2.getFolder("usr", false);
System.out.println("usr folder" + usrfolder);
How can I parse all the headers of the MQ Message?
DataInput in = new DataInputStream (new ByteArrayInputStream (b));
What's that about? Not sure why you want to do that.
It should just be:
MQMessage message = new MQMessage();
queue.get(message, getOptions);
MQHeaderList headersfoundlist = new MQHeaderList(message);
System.out.println("headersfoundlist size: " + headersfoundlist.size());
Read more here.
Update:
#anshu's comment about it not working, well, I've always found MQHeaderList class to be very buggy. Hence, that is why I don't use it.
Also, 99.99% messages in MQ will only ever have 1 embedded MQ header (i.e. MQRFH2). Note: A JMS message == MQRFH2 message. The only case where you will find 2 embedded MQ headers are for messages on the Dead Letter Queue.
i.e.
{MQDLH}{MQRFH2}{message payload}
Is there a real need for your application to process multiple embedded MQ headers? Is your application putting/getting JMS messages (aka MQRFH2 messages)?
If so then you should do something like the following:
queue.get(receiveMsg, gmo);
if (CMQC.MQFMT_RF_HEADER_2.equals(receiveMsg.format))
{
receiveMsg.seek(0);
MQRFH2 rfh2 = new MQRFH2(receiveMsg);
int strucLen = rfh2.getStrucLength();
int encoding = rfh2.getEncoding();
int CCSID = rfh2.getCodedCharSetId();
String format= rfh2.getFormat();
int flags = rfh2.getFlags();
int nameValueCCSID = rfh2.getNameValueCCSID();
String[] folderStrings = rfh2.getFolderStrings();
for (String folder : folderStrings)
System.out.println.logger("Folder: "+folder);
if (CMQC.MQFMT_STRING.equals(format))
{
String msgStr = receiveMsg.readStringOfByteLength(receiveMsg.getDataLength());
System.out.println.logger("Data: "+msgStr);
}
else if (CMQC.MQFMT_NONE.equals(format))
{
byte[] b = new byte[receiveMsg.getDataLength()];
receiveMsg.readFully(b);
System.out.println.logger("Data: "+new String(b));
}
}
else if ( (CMQC.MQFMT_STRING.equals(receiveMsg.format)) ||
(CMQC.MQFMT_NONE.equals(receiveMsg.format)) )
{
Enumeration<String> props = receiveMsg.getPropertyNames("%");
if (props != null)
{
System.out.println.logger("Named Properties:");
while (props.hasMoreElements())
{
String propName = props.nextElement();
Object o = receiveMsg.getObjectProperty(propName);
System.out.println.logger(" Name="+propName+" : Value="+o);
}
}
if (CMQC.MQFMT_STRING.equals(receiveMsg.format))
{
String msgStr = receiveMsg.readStringOfByteLength(receiveMsg.getMessageLength());
System.out.println.logger("Data: "+msgStr);
}
else
{
byte[] b = new byte[receiveMsg.getMessageLength()];
receiveMsg.readFully(b);
System.out.println.logger("Data: "+new String(b));
}
}
else
{
byte[] b = new byte[receiveMsg.getMessageLength()];
receiveMsg.readFully(b);
System.out.println.logger("Data: "+new String(b));
}
I found the mistake in my code. I have a few more steps before reading the headers. It was moving the cursor in message buffer to the end.
I added message.setDataOffset(0); before reading headers and it worked.
public string WriteMsg(string strInputMsg)
{
string strReturn = "";
try
{
MQQueue queue = null;
MQQueueManager QueueManagerName = null ;
QueueManagerName = new MQQueueManager("GRBAAQM");
queue = QueueManagerName.AccessQueue(QueueName, MQC.MQOO_OUTPUT
+ MQC.MQOO_FAIL_IF_QUIESCING);
message = strInputMsg;
queueMessage = new MQMessage();
queueMessage.WriteString(message);
queueMessage.Format = MQC.MQFMT_STRING;
queuePutMessageOptions = new MQPutMessageOptions();
queue.Put(queueMessage, queuePutMessageOptions);
strReturn = "Message sent to the queue successfully";
}
catch (MQException MQexp)
{
strReturn = "Exception: " + MQexp.Message;
}
catch (Exception exp)
{
strReturn = "Exception: " + exp.Message;
}
return strReturn;
}
public string ReadMsg()
{
String strReturn = "";
try
{
MQQueue queue = null;
MQQueueManager QueueManagerName = null;
QueueManagerName = new MQQueueManager("GRBAAQM");
queue = QueueManagerName.AccessQueue(QueueName, MQC.MQOO_INPUT_AS_Q_DEF +
MQC.MQOO_FAIL_IF_QUIESCING);
queueMessage = new MQMessage();
queueMessage.Format = MQC.MQFMT_STRING;
queueGetMessageOptions = new MQGetMessageOptions();
queue.Get(queueMessage, queueGetMessageOptions);
strReturn =
queueMessage.ReadString(queueMessage.MessageLength);
}
catch (MQException MQexp)
{
strReturn = "Exception : " + MQexp.Message;
}
catch (Exception exp)
{
strReturn = "Exception: " + exp.Message;
}
return strReturn;
}
These two methods in this program helps us to read the messages from queue and displays but how to insert this feature while reading message FROM queue, read only if the message count has reached 10.
Why do you care how many messages are in the queue? MQ is NOT a database. If a message is in the queue then it should be processed. If you need to group messages together then have the sender use MQ's message grouping feature.
Did you read about MQ triggering? A program can be triggered (started) based on a triggering event. i.e. Trigger-first, trigger-every & trigger-depth.
I have a requirement for a batch job that should send out emails.However I have to break it out in such a fashion that I need to handover the email details to another system via messaging which will then read the messages placed and send out emails leisurely.
My emails have attachments.How do I achieve this? There could be multiple attachments for a given email.
I read about bytes message but how do I use it for multiple attachments for a given email message?
Any thoughts about this?
You could send one JMS message containing email details (from, to list, subject, text), and after that send attachments as JMS bytes message, each attachment message with the same custom identifier.
Sender side
// create JMS Bytes message with mail content
// MailData class should implement java.io.Serializable)
MailData mailData = new MailData();
// emailID could be GUID or anything else that would uniquely identify mail
mailData.setEmailID(emailID);
mailData.setFrom(from);
mailData.setToList(toList);
mailData.setSubject(subject);
mailData.setText(text);
BytesMessage msg = session.createBytesMessage();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(mailData);
out.close();
bos.close();
msg.writeBytes(bos.toByteArray());
producer.send(msg);
// for the sake of simplicity, object attachment contains attachment name, MIME type
// and value as byte array
for(Attachment att : attachmentList) {
BytesMessage msgAtt = session.createBytesMessage();
// emailID
msgAtt.setStringProperty("emailId", emailID);
msgAtt.setStringProperty("fileName", att.getAttachmentName());
msgAtt.setStringProperty("mimeType", att.getMimeType());
// set bytes message payload to attachment content
msgAtt.writeBytes(att.getValue());
producer.send(msgAtt);
}
Receiver side
BytesMessage bytesMessage = (BytesMessage) message;
byte[] bytes = new byte[(int) bytesMessage.getBodyLength()];
bytesMessage.readBytes(bytes);
ByteArrayInputStream bis = new ByteArrayInputStream(bytesMessage);
ObjectInputStream in = new ObjectInputStream(bis);
MailData mailData = (MailData) in.readObject();
in.close();
bis.close();
// get data from queue with the same emailID
MessageConsumer consumer = session.createConsumer(queue, "emailID='"
+ mailData.getEmailID() + "'");
connection.start();
Message attMsg = null;
while((attMsg = consumer.receiveNoWait()) != null) {
String fileName = attMsg.getStringProperty("fileName");
String mimeType = att.getStringProperty("mimeType");
BytesMessage bytesMessage = (BytesMessage) attMsg;
byte[] attachmentValue = new byte[(int) bytesMessage.getBodyLength()];
bytesMessage.readBytes(attachmentValue);
}
After successfully sending my message, i'm just browsing for it..
But, i get only the messages which i send # that time..That is, i don't see any previous messages which i sent to the queue.
I'm using a simple java client to send messages.
My sample code is;
sender.send(message);
Enumeration enu = browser.getEnumeration();
List list = new ArrayList();
while (enu.hasMoreElements()) {
TextMessage message= (TextMessage) enu.nextElement();
System.out.println("** " + list.size());
list.add(message.getText());
}
for (int i = 0; i < list.size(); i++) {
System.out.println("Browsed msg " + list.get(i));
}
I don't use consumers here.. So , how i loose my messages from the queue? :(
I'm trying with OracleAQ..