I have an webapp that is expected to fetch and display data from an External App which is accessible only via messaging (JMS).
So, if a user submits a request on a browser, the same HTTP request thread will have to interact with the Messaging system (MQ Series) such that the same request thread can display the data received from the Messaging System.
Is there a pattern I can make use of here? I saw some vague references on the net that use "Correlation ID" in this way:
Msg m = new TextMsg("findDataXYZ");
String cr_id = m.setCorrelationID(id);
sendQueue.send(m).
// now start listening to the Queue for a msg that bears that specific cr_id
Response r = receiverQueue.receive(cr_id);
Is there something better out there? The other patterns I found expect the response to be received asynchronously.. which is not an option for me, since I have to send the response back on the same HTTP request.
The request/reply messaging pattern is useful for your requirement. You typically use a CorrelationId to relate request & reply messages.
While sending request message you set JMSReplyTo destination on the message. Typically a temporary queue is used as JMSReplyTo destination. When creating a consumer to receive response use a selector with JMSCorrelationId, something like
cons = session.createConsumer(tempDestination,"JMSCorrelationId="+requestMsg.JMSMessageId);
At the other end, the application that is processing the request message must use the JMSReplyTo destination to send response. It must also use the MessageId of the request message and set it as CorrelationId of the response message.
First, open the response queue. Then pass that object to the set reply-to method on the message. That way the service responding to your request knows where to send the reply. Typically the service will copy the message ID to the correlation ID field so when you send the message, take the message ID you get back and use that to listen on the reply queue. Of course if you use a dynamic reply-to queue even that isn't neessary - just listen for the next message on the queue.
There's sample code that shows all of this. If you installed to the default location, the sample code lives at "C:\Program Files (x86)\IBM\WebSphere MQ\tools\jms\samples\simple\SimpleRequestor.java" on a Windows box or /var/mqm/toolsjms/samples/simple/SimpleRequestor.java on a *nix box.
And on the off chance you are wondering "install what, exactly?" the WMQ client install is downloadable for free as SupportPac MQC71.
Related
Hi I am writing a telegram client using https://github.com/rubenlagus/TelegramApi that listen to incoming messages but I noticed some relevant messages carried in 'Polls' could not be read.
After a few debugging, it appears when such message is received, the incoming 'MessageMedia' part of the TLMessage being deserialized is mapped to messageMediaUnsupported#9f84f49e
According to documentation it means it is 'not supported by current client version'.
Indeed, I could see no implementation for messageMediaPoll message media in org.telegram.api.message.media package, and I could add it. But, how to have the server consider my client as valid for receiving such media?
I was going through the tutorial shared by RabbitMQ here
I am assuming that the client code below
while (true)
{
var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
if (ea.BasicProperties.CorrelationId == corrId)
{
return Encoding.UTF8.GetString(ea.Body);
}
}
Would receive all messages on the queue and will unnecessarily iterate through messages not designated for it. Is their anyway we can avoid it i.e we can modify the client to only receive the messages intended for it only.
The basic work that i intend to achieve through RabbitMQ is Request-Response pattern where a request would be received by web-service which will send data in a queue the data object would have a unique reference number . This would be received by an asynchronous tcp-client which will send data on a tcp/ip layer based on message it had received.
On receiving reply from the asynchronous channel of tcp/ip the channel would parse the data and respond back on the queue with the corresponding request reference number.
The RPC approach is well suited for it but the client code shared have this shortcoming would appreciate feedback on it.
Actually I didn’t understand well your aim, but when you create an RPC model, you have to create an “reply queue”, this queue is bound only to the client.
It means that you will receive back only the client messages, and not all messages.
Since the Rabbitmq RPC model is asynchronous you can execute more than one request without wait the responses and replies could not have the same publish order.
The correlation id is necessary to map your client requests with the replies, so there are not "unnecessarily" messages
hope it helps
We are sending a message to Websphere MQ Queue. While sending the message we are setting the REPLY TO QUEUE NAME and JMSCOrrelationID. We also set the USER IDENTIFIER. The code snippet is as follows.
Message msg = session.createTextMessage((String) message);
Destination codeDestination = session.createQueue("queue://" + replyToQueueMgr + "/" + replyToQueueName);
msg.setJMSReplyTo(codeDestination);
msg.setIntProperty(JmsConstants.JMS_IBM_REPORT_COD, MQC.MQRO_COD);
msg.setJMSCorrelationID(msgCorrelId);
msg.setStringProperty(JmsConstants.JMS_IBM_MQMD_USERIDENTIFIER, "abc");
producer.send(msg);
Please note that we have ensure that all the fields which we set are not null. Also the user abc is a valid user because if not then the CODs should go to DEAD LETTER QUEUE but there are no messages in it. Still after the message is picked up we get a COD which has JMSCorrelationID as null. In COD Processor we are listening on the replyToQueuename.
String correlationID = (String)eventContext.getMessage().getInboundProperty("JMSCorrelationID");
On checking above correlation ID is null. ALso the message payload is of {null_payload} type of NullPayload class of mule. I know that body would be NULL because we set MQC.MQRO_COD. But I dont undertand how the correlationId got wiped out.
Please advise if there is any configuration at the Webview MQ end whih could cause such a behaviour? Or is there something missing in the way we are setting the header properties?
UPDATE
The queue that we are sending the message to with COD information is an alias to a TOPIC. There are 2 subscribers to this TOPIC and we observed that there were instances where we received multiple COD's when both the subscribers picked up the messages. Is there any way to ensure that the TOPIC sends a single COD after all the subscribers have picked up the message? Could this QM setup be the cause of the COD with null?
User Identifier
When a message is published, each subscriber gets a copy of the message with a unique message ID and with the identity context fields in the MQMD (UserID, AccountingToken, ApplIdentityData) all set to the subscriber's context. So it doesn't matter what you set in the MQMD UserID of the message you publish, all the copies will have the subscriber user ID in them. This user ID will, by definition, exist where he subscriber is so the CODs will be able to be put.
Correlation ID with Pub/Sub
You can ensure the correlation ID from the publisher is sent all the way through to the subscriber, by ensuring the subscription is made using MQSO_SET_CORREL_ID and setting the MQSO SubCorrelId to MQCI_NONE.
One COD for multiple messages
Since there are multiple independent messages, each with the COD Report Option set, you will get multiple report messages. There is no setting to combine these, however you could write an intermediate application to combine then if your main application wants only one.
Passing Correl ID back in a Report Message
By default the report option will send back the message ID in the Correl ID of the report message. If you want to have the Correl ID passed back, you should use MQRO_PASS_CORREL_ID.
Further Reading
Report Option
The issue is not with MQ configuration but with Mule endpoint configuration. The COD which were sent with nullpayload were actually sent by my own mule application jmsRepyToHandler. There is some default configuration in Mule which seems to be causing this behavior.
Analysis
Application sends a message to the Queue which is alias to a TOPIC with two subscribers
Once both the subscribers consume the message we get 2 COD as expected.
These COD are consumed by my MULE application and after processing the MULE application again sends COD to same queue with null correlation Id.
UPDATE: Mule Fix to avoid default ReplyTo
For the fix you need to override getReplyToHandler method of Mule JMSConnector as follows
if (disableReplyTo) {
return new DisableJmsReplyToHandler(this, getDefaultResponseTransformers(endpoint));
}else {
return super.getReplyToHandler(endpoint);
}
Set the property disableReplyTo as true so that above code provide DisableJmsReplyToHandler instead of the default one.
Suppose both reply and request are being sent to the same topic, and now I'm subscribed to it. How do I identify which of them is which?
Try setting message property on the messages which you publish to the topic. You set a string property on each message, e.g. message_type=”request” or message_type=”response”. When you consume the message on the listener you can read the property to identify if the message is request or response.
Another way of doing it is by starting two listeners with message selector properties. One which will only consume messages with message_type property as “request” and another which will only consume messages with message_type property as “response”.
There is an easy way too: The request comes in first, so I can check for a smaller timestep than the response. Which will identify it as the request.
I can't find documentation for reply processing with gateways and service activators.
If I have gateway which:
1) sends requests to channel ReqChannel
2) accepts replies on channel RepChannel
ReqChannel is connected to router, that routes incoming messages to one of some service activators, let say AServiceActivator and BServiceActivator and that service activators have a configured output-channel="RepChannel".
And if I execute more than one method call on gateway's interface asynchronously or simultaneously from different threads, how gateway will correlate incoming replies to actual service caller?
The gateway creates a temporary reply channel and puts it in the header of the message. This mechanism provides the necessary correlation because each message gets its own reply channel.
If the final consumer (say a service-activator) has no output-channel, the framework automatically sends the reply to the replyChannel header.
For this reason, it is generally not necessary to declare a reply-channel on the gateway for the final consumer to send to.
However, there are times when this is useful - such as if you want to wire-tap the reply channel, or make it a publish-subscribe channel, so the result goes to multiple places.
In this case (when there is a reply-channel on the gateway, and the final consumer sends a message there), the framework simply bridges the explicitly declared reply-channel to the temporary reply channel in the message header.
For this reason, it is critical to retain the replyChannel header in your flow. You can't send some arbitrary reply to a reply-channel, unless you include the original message's replyChannel header.