I am sending messages to a remote queue, to which I have no control.
I send a xml file as message but when the application reads the message it gets a message header like
<mcd><Msd>jms_text</Msd></mcd> \0\0\0l<jms><Dst>queue:///TEST</Dst><Tms>1281475843707</Tms><Cid></Cid><Dlv>1</Dlv></jms>
i don't want this message header to be present and my code for sending this message is as follows:
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",this.initialFactory);
props.setProperty("java.naming.provider.url", url);
Context context = new InitialContext(props);
QueueConnectionFactory qcf = (QueueConnectionFactory) context.lookup(this.context);
qConn = qcf.createQueueConnection();
queue = (Queue)context.lookup(name);
qSession = qConn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
qConn.start();
QueueSender send = qSession.createSender(queue);
String text = "My xml file";
TextMessage tm = qSession.createTextMessage(text);
send.send(tm);
send.close();
How do I avoid this ?
It appears that you are sending a jms message to a non jms destination. How is the message being consumed on the destination? Is it expecting a native MQ message? The receiver is not understanding the MQRFH2 header that stores the JMS header properties.
You should either configure the destination to understand jms or your can do something like the following to tell the mq jms that your receiver is a non-jms client.
((com.ibm.mq.jms.MQQueue) queue).setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ);
Have a look at the properties for JMS objects as listed in the docs. On the administered object there is a property called TARGCLIENT which should be set to 'MQ'. Although you may have no control over the administered object, it is the responsibility of the person who administers the managed objects to set this property correctly. If the destination does not understand the RFH2 headers (which WMQ v6 uses to hold JMS properties) then any WMQ JMS applications which send messages to that destination must have that property set.
Incidentally, the fact that you are having this problem tends to indicate that the application consuming messages is still at v6. Please be aware that v6.0 of WMQ is end-of-life as of Sept 2011. If you switch to v7 now at both the QMgr and the client side, you can manage this with simple settings on the queue itself. The legacy app will understand the messages regardless of whether they have an RFH2 attached and the client app will see the responses as JMS messages regardless of whether the legacy app adds RFH2 headers. Move to v7 now, save your self a whole lot of trouble developing this app and also avoid having to migrate to v7 next year.
WMQ v7 client downloads are available here
Update: End-of-life for WMQ V6 was pushed back to September 2012.
Related
I am newbie to Websphere MQ and i have some basic understanding on the concept of MQ. I know that MQ client would create a message (with MQMD and application data) and then send to MQ manager. MQ client will get the correct response back from MQ Manager. Supposedly there are many messages on the MQ Queue Manager, how does MQ client able to retrieve the right messages? What determines the uniqueness of a MQ message?
There are different ways this can be approached - one common way is for the applications processing the messages to use the message ID and correlation ID fields. The message ID can be randomly generated and saved then copied to correlation ID field to be match when the reply is sent. Applications can do gets matching on those fields in the message header.
I suggest you read through the application programming guide and reference in the knowledge center.
I have setup a topic to MQ messaging. The setup is done like in the documentation "MQ Connectivity scenario 2: Fan in per device notification" it appears as though Messagesight adds data the the message when it arrives at MQ destination. (possibly JMS header data). Is there something that has to be setup either on messagesight or MQ manager to remove the data and only leave the message?
I have a Java JMS application that reads messages from a MQ queue. My application can successfully read a message and pull out the JMS headers (e.g. JMSDeliveryMode, JMSPriority etc) and the message body, but I can not access the <usr> folder part of the message.
I am placing messages on a queue using RFHutil. Under the RFH tab I am ticking 'Include RFH V2 Headers' and 'usr', and under the usr tab I have test1=1. I can see the <usr><test1>1</test1></usr> in the message if I browse the queue using MQExplorer, so I think I'm setting the usr folder correctly.
I have outputted the whole of message.getPropertyNames() enumeration (as discussed at topic JMS passing entire Application data <usr> block, but my usr fields are not under there. My message body also does not contain my usr fields.
I've also read on the MQ v7 info center you need to set WMQ_MESSAGE_BODY to WMQ_MESSAGE_BODY_MQ, but I am using v6MQ and do not know if this is relevant/how to set this value.
How can I get access to the usr folder using the JMS API?
Any help/pointers would be much appreciated as I am fairly new to JMS programming.
A first question is why is the USR folder of importance? Are you attempting to get your JMS application to interoperate with messages that put using another application that writes custom RFH2 headers.
RFHUtil is primarily used for test purposes.
MQ JMS originally used the RFH2 heasder to specifically send the JMS properties. Therefore the MQ JMS code reads the message, removes the RFH2 and processes it into a full JMS Message.
If you want the JMS API to fully read the RFH2, then the properties for reading the MQ message you've highlighted are correct. However those are not in MQ v6. Be aware that mq v6 and V7.0.1 are now out of support. Would strongly recommend that you investigate upgrading to MQ v8 - at minimum MQ 7.5.
CLients are freely downloadable if you are a developer and connecting to an estbalished QueueManager. Client versions don't have to match the QM.
We are using Websphere MQ8 and thinking about using durable Topics to implement a Publish and Subscribe pattern.
We are using Queues already and Hermes JMS-Browser to correct erroneous Queue-Messages.
I know that you can use Hermes to subscribe to topics but i think you cannot access and modify messages that are already on hold for a specific client.
So I would like to know - how do you handle problems when there are durable messages for a specific client application that the client can't consume, e.g. because the message has wrong format?
Do you have to delete alle undelivered messages for this client? Or is there some tooling that can do this?
How do you handle problems when there are durable messages for a
specific client application that the client can't consume, e.g.
because the message has wrong format ?
Consuming Application (Client) should have proper exception handling
and it should throw out all bad/poison messages.
Do you have to delete all undelivered messages for this client? Or is there some tooling that can do this?
The messages will be deleted automatically by the MQ server once the
TTL (Time To Live) expires. We can't manually delete those messages as
they belong/meant for the original client (which is a durable
subscriber).
The below link explains well on the concept of JMS durable subscriptions:
https://docs.oracle.com/cd/E19798-01/821-1841/bncgd/index.html
Also I have provided the below sample code for the tool, which logs (doesn't delete) the messages from a durable subscription topic:
InitialContext ctx = new InitialContext();
Topic topic = (Topic)ctx.lookup("myJMSTopic1");
TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx.lookup("topicConnFactory");
TopicConnection topicConn = connFactory.createTopicConnection();
topicConn.setClientID("myToolId1"); //Use a different client id than original subscriber
TopicSession topicSession = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
TopicSubscriber topicSubscriber = topicSession.createDurableSubscriber(topic, "myClientExistingDuraSubName"); // this is where you have to provide the original client's durable subscription name
while(true) {
Message message = topicSubscriber.receive();
TextMessage txtMsg = (TextMessage)message;
logger.info(txtMsg.getText());
}
Is it possible to configure the topic to store a copy of just the last message and send this to new connections without knowing client identifiers or other info?
Update:
From the info provided by Shashi I found this two pages where they describe a use case similar to mine (applied over stock prices) by using retroactive consumer and a subscription recovery policy. How ever I'm not getting the desired behaviour. What I currently do is:
Include in the activemq the folowing lines in the policyEntry for topic=">"
<subscriptionRecoveryPolicy>
<fixedCountSubscriptionRecoveryPolicy maximumSize="1"/>
</subscriptionRecoveryPolicy>
Add to the URL used to connect to the brocker (using activemq-cpp) consumer.retroactive=true.
Set the consumer has durable. (But I strongly think this is not want since I only need the last one, but without it I didn't get any message when starting the consumer for the second time)
Start up the broker.
Start the consumer.
Send a message to the topic using the activemq web admin console. (I receive it in the consumer, as expected)
Stop consumer.
Send another message to the topic.
Start consumer. I receive the message, also as expected.
However, if the consumer receives a message, then it goes offline (stop process) and then I restart it, it doesn't get the last message back.
The goal is to whenever the consumer starts get the last message, no mater what (obviously, except when there weren't messages sent to the topic).
Any ideas on what I'm missing?
Background:
I have a device which publishes his data to a topic when ever its data changes. A variable number of consumer may be connected to this topic, from 0 to less than 10. There is only one publisher in the topic and always publish all of his data as a single message (little data, just a couple of fields of a sensor reading). The publication rate of this information is variable, not necessarily time based, when something changes a new updated message is sent to the broker.
The problem is that when a new consumer connects to the topic it has no data of the device readings until a new message is send to the topic by the device. This could be solve by creating an additional queue so new connections can subscribe to the topic and then request the device for the current reading through the queue (the device would consume the queue message which would be a request for data, and then response in the same queue).
But Since the messages send to the topic are always information complete I was wondering if is it possible to configure the topic to store a copy of just the last message and send this to new connections without know client identifiers or other info?
Current broker in use is ActiveMQ.
What you want is to have retroactive consumers and to set the lastImageSubscriptionRecoveryPolicy subscription recovery policy on the topic. Shashi is correct in saying that the following syntax for setting a consumer to be retroactive works only with Openwire
topic = new ActiveMQTopic("TEST.Topic?consumer.retroactive=true");
In your case, what you can do is to configure all consumers to be retroactive in broker config with alwaysRetroactive="true". I tested that this works even for the AMQP protocol (library qpid-jms-client) and I suspect it will work for all protocols.
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic="FOO.>" alwaysRetroactive="true">
<subscriptionRecoveryPolicy>
<lastImageSubscriptionRecoveryPolicy />
</subscriptionRecoveryPolicy>
</policyEntry>
The configuration example is taken from https://github.com/apache/activemq/blob/master/activemq-unit-tests/src/test/resources/org/apache/activemq/test/retroactive/activemq-message-query.xml
Messaging providers (WebSphere MQ for example) have a feature called Retained Publication. With this feature the last published message on a topic is retained by the messaging provider and delivered to a new consumer who comes in after a message has been published on a given topic.
Retained Publication may be supported by Active MQ in it's native interface. This link talks about consumer.retroactive which is available for OpenWire only.
A publisher will tell the messaging provider to retain a publication by setting a property on the message before publishing. Below is how it is done using WebSphere MQ.
// set as a retained publication
msg.setIntProperty(JmsConstants.JMS_IBM_RETAIN, JmsConstants.RETAIN_PUBLICATION)