how to read only specific queue messages based on message header property - jms

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")..

Related

How return a Message (from Spring) to represent that the information was not found?

I'm working with messaging on Spring and I had a simple question.
When another services sends a message requesting an information that does not exists for the service that are able to answer, the first thing that I thoutght was pass a "null" do the payload:
MyResponse myResponse = service.find(id); //ops, the information with this id does not exists
Message<MyResponse> message = MessageBuilder
.withPayload(myResponse) // the information does not exists, so null
.copyHeadersIfAbsent(request.getHeaders())
.build();
But the method withPayload not accept null. So, what is the good practice or alternative to fill this message with a "empty" value to the original request receive the result and know that this information does not exists?
For now I'm passing a empty object (new MyResponse()) to the payload, but this could create a confusion for who consumes the message. I could create another class to represent this "not exists" state, but I'm trying to understand my options now.
Thanks!
The null payload doesn't bring too much information and isn't supported by many network protocols. More over there are many places in the framework which are based on the payload type, but if it is a null we might not have any information what and how to do with it. In some components the null return value is a signal to stop the flow and don't produce any messages downstream to reply.
The solution you may go is like constant object (MyNullResponse) to indicate that it is about a null.
You might also consider a way with an exception instead of an attempt to return null. Let's consider that you do some post-search processing and a bunch of filtering and conversion steps. In case of null your message will still travel all the flow down. But when we deal with an exception (like it is with the javax.persistence.EntityNotFoundException) we just bubble the problem to end-user immediately. And that's already the target service responsibility to represent that exception as a comprehensible message for end-user.
We have a JIRA ticket about null payload support. You can read there about more reasons and what other people think on the matter. My idea to allow something on the matter is like Optional.empty(). Then we can map it to null easily on the target end-user code.
You must clearly differentiate between The response itself ( in your case MyResponse object) and the existence or not of the information which something relative to you business logic, the message that you construct must be as generic as possible not hard coupled to your service layer, simple reason => the message is just a message you send to consumers , so if possible try to embed the existence or not of the information in your object MyResponse (Boolean Flag) , and construct it on the fly after invoking your service
instead of
MyResponse myResponse = service.find(id);
you can try this :
CustomResponse myResponse = service.find(id);
// use helper class to respect DRY principal if you need it somewhere
MyResponse messageReponse = ResponseBuilder.constructResponse(myReponse);
Message<MyResponse> message =// .. construct you message
In the example above ResponseBuilder take care of myResponse if it null, and fully create the response ( you could integrate all cases .. )
I would like to share with you guys my solution after read the #Artem answer.
I created an OptionalMessage class, very similar of Optional class from Java 8+. As I'm using application/json as content-type for messages.
I can use this OptionalMessage in different messages:
OptionalMessage optionalMessage = messaging.find(id);
if (optionalMessage.isPresent()) {
MyMessage myMessage = optionalMessage.getContent();
}
It has also the methods of() and empty(), used in the another side to populate the OptionalMessage.
The Json structure generated follow this example:
{
"content": { /*attributes */}
}
When we have no content (my "null" return), the Json look like this:
{
"content": null
}
I tried to use generics (OptionalMessage<MyMessage>), but I would need to change my Jackson setup (on IntegrationFlow DSL) to not receive the error java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to MyMessage when calling the getContent method.

Obtain dynamic object in MassTransit consumer

We use an empty marker interface for a group of events that need to be saved to some audit log database.
However, in the consumer, messages are cast to this interface, so we get an empty object.
What we actually need is to get the "dynamic" or get hold on the message body so we can send it to the audit database "as-is" since our database can save JSON documents. But we cannot see how we can get the message body as JSON from the context. Is it possible at all?
If you really wanted to be efficient, you could keep your consumer using the interface as it is today, but then, in your consumer, get the JToken from the message context, and use the JToken to save the JSON of the message. This way, your consumer doesn't need to know every single object type nor have the assembly for that object type.
public async Task Consume(ConsumeContext<IEvent> context)
{
ConsumeContext<JToken> jsonContext;
if(context.TryGetMessage(out jsonContext))
{
_eventStore.Save(jsonContext.Message); // the JToken
}
}

AWS SQS JSON format when receiving message from SNS with Ruby SDK

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

JMS-like Message Selectors for AMQP (ActiveMQ / RabbitMQ)

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.

I use jersey + protobuf, How can I pass a meaningful error message back to client?

How can I pass a meaningful error message back to client? I can implement the ExceptionMapper to produce meaningful error message.
But how can I have writer to pass the message back to client?
I haven't used jersey personally, but my general approach here would be to simply include the result-state (including error message) in the returned message, i.e.
message GetCustomerResult {
optional string errorMessage = 1;
optional Customer customer = 2;
}
or similar, such that all your messages have a consistent way to report failure. If your error state is more than just a string, you could declare a message for that, and include it on all results, so you can just pass that to any shared error-handling code.
You can throw WebApplicationException which takes Response in a constructor and gets mapped by Jersey automatically to that response. You can put the meaningful message into the response body.

Resources