Is there anything similar to JMS message selectors for RabbitMQ? Or must some code be written to parse and select the messages?
Thanks.
It's called "amqp routing key".
You can find the different here:
http://www.wmrichards.com/amqp.pdf
And you can find some example about the routing-key here:
http://www.rabbitmq.com/tutorials/tutorial-four-python.html
AMQP routing key with direct/topic exchanges work well if the selector is always on a single string field. If your selectors are all of the form message_type = 'foo' then you would use message_type as your routing key.
If the message filter uses multiple/different fields, then you could use the amq.match exchange, which would route messages that match any or all header values to the related queue. This would handle selectors like field1 = 'value' OR field2 = 'value' and cases where different consumers selectively consume based on different attributes.
I think JMS message selectors also let you do more complex logic and comparison operators like greater-than, less-than, etc. and I haven't found an equivalent of that with AMQP/RabbitMQ.
Related
This is the attribute and value which my pub/sub subscription will be expected to filter:
'objectId': 'event-notifications-test/_MANIFEST'
However, I am not concerned about the prefix of the value (event-notifications-test/) changing - I only want to filter the message from the topic if it contains '_MANIFEST'. If I was interested in the prefix, I expect I would need to use something like this:
hasPrefix(attributes.name, "co")
How can I filter the message based on the suffix of the value i.e. '_MANIFEST'?
It is not possible to filter directly on a suffix, no. Your two options are:
When publishing, write the suffix out as a separate attribute.
Filter at the application level when you receive a message by checking the suffix and acking the message without processing it.
I want to filter according to header. If some of property is not null, send data from that property to different route.
from(SAVE_RECEIVED_IDS)
.process(exchange -> {
//here i set true for filters because there is faulty data
exchange.getIn().setFault(true); //for PROCESS_FAULTY route
//if filter catches, it should get and send this but it does not come here
exchange.setProperty("faultyOnes","somearraylistOrData"); //for PROCESS_FAULTY route
exchange.setProperty("other fields irrelevant to faulty","somearraylistOrData");//for route GO_NEXT_ROUTE
})
//here i neeed to filter if value is ture
.filter(exchange -> exchange.getIn().isFault()) //it does not come here
.to(PROCESS_FAULTY)
.end() //end for filter
.to(GO_NEXT_ROUTE) //if there is no faulty come here. if there is faulty, after send come here.
.end() //end from()
or should i use choice and when?
.choice()
.when(header("foo").isEqualTo("bar"))
...
.when(header("foo").isEqualTo("chese"))
...
.otherwise()
....
.end(),
like this? I use isFaulty but headers are better or properties? But where do i keep faulty data? Thanks for answers
First, please be careful while setting message as faulty. This is primarily designed for irrecoverable errors which should trigger error recovery routines.
headers are better or properties? But where do i keep faulty data?
Take a look at Passing values between processors in apache camel, also go through the following answer from Claus on same thread. Most notably, properties are safely stored for the entire duration of the processing of the message in Camel. In contrast, headers are part of the message protocol, and may not be propagated during routing (quoted form Claus answer) - in short, properties are better suited especially if your message is also passing across protocols (http, jms etc). So use properties for storing faulty data.
I have a list of messages in activemq queue. each message has a custom header property with value. How I should be able to access only those messages whose custom header property value = 123.?
I am using something like below to pick a message from queue. How to pick all messages which or a single message which has customHeaderProperty =123.?
ConsumerTemplate consumerTemplate = camelContext.createConsumerTemplate();
Exchange ex = consumerTemplate.receive("activemq:queueName",10000);
String data = ex.getIn().getBody(String.class);
String number = ex.getIn().getHeader("customProperty", String.class);
Use message selectors on the consumer. A selector is a SQL like query. So you could write something like myCustomHeader = 123. Here is a pretty good cheat sheet.
Since you tagged the question with apache-camel, I guess you are working with a Camel setup. In that case, you need to supply the selector to Camel. Something like from("activemq:queue:myqueue?selector=myCustomHeader%3D123")..
i have a requirement in which i need to filter JMS messages according to XPATH.
I tried to use a jca property as shown below. But it did not pick any JMS messages.
property name="MessageSelector" value="JMS_BEA_SELECT('xpath','/ns1:books/ns1:book[2]/ns1:price/text()') = '20'"/>
i tried to use multiple variants in the value part but anything doesn't work.
Is any syntax available for this or any other way for doing this task.
NOTE: i do not want to use headers
Usually, you cannot use XPATH in selectors when using JMS. However, ActiveMQ supports Xpath selectors: http://activemq.apache.org/selectors.html
Obviously, your messages must then be TextMessages containing XML bodies, as above documentation suggests.
I have an SQS queue which is subscribed to a SNS topic. When I publish a new notification to the topic, I use the following code (within a Sinatra app):
jsonMessage = {
"announcement" => {
"first_name" => results['first_name'][:s],
"last_name" => results['last_name'][:s],
"loc_code" => results['location'][:s],
"note" => params['note_content']
}
}
msgid = #announcments_topic.publish(jsonMessage.to_json,
{subject: "Note Created",
message_structure: 'json' })
When my queue listener picks up this notification, the message section of the corresponding hash looks like this:
"Message"=>"{\"announcement\":{\"first_name\":\"Eve\",\"last_name\":\"Salt\",\"loc_code\":\"Location\",\"note\":\"test\"}}"
In my queue listener, I want to use this hash, but when I try to use
JSON.parse(result['Message'])
I get an unexpected token error because of the escaped double quotes. Any suggestions on how I can fix this? Am I not sending my notification as JSON properly? How can I get sns/sqs to not escape the double quotes?
Found the answer.
The problem was the way I was getting the JSON. I needed to use JSON.load(result['Message']), instead of JSON.parse(...).
SNS publish method actually apends escape character before publishing the message.
Here is the doc http://docs.aws.amazon.com/sns/latest/api/API_Publish.html
JSON-specific constraints:
Keys in the JSON object that correspond to supported transport protocols must have simple JSON string values.
The values will be parsed (unescaped) before they are used in outgoing messages.
Outbound notifications are JSON encoded (meaning that the characters will be reescaped for sending).
Values have a minimum length of 0 (the empty string, "", is allowed).
Values have a maximum length bounded by the overall message size (so, including multiple protocols may limit message sizes).
Non-string values will cause the key to be ignored.
Keys that do not correspond to supported transport protocols are ignored.
Duplicate keys are not allowed.
Failure to parse or validate any key or value in the message will cause the Publish call to return an error (no partial delivery).
So in java, we get the json message using below instruction. this removes the escape character from the incoming message.
void handle(Message message) {
**String serializedMessage = SNSMessage.fromJson(message).getMessage();**
}
You might also consider turning on raw message delivery on the topic subscription if you don't want to deal with the consumer having to remove the escape characters from the incoming messages.
Please refer to the following documentation in AWS:
http://docs.aws.amazon.com/sns/latest/dg/large-payload-raw-message.html