Goal - to configure Solace Message-Broker to route messages to different HTTP consumer based on either http-headers or request-target's path.
I'm new to Solace... and I think it would be possible if I configure a separate message-vpn and assign different ports for REST. But ability to dynamically route based on payload might have some merit.
Messages in Solace are routed based on the topic or queues. With Solace's REST messaging feature, the topic or queue that the producer is publishing to is determined by the HTTP request-target.
e.g.
To send to topic "A", use http://[solaceIP:restPort]/TOPIC/A
To send to queue "B", use http://[solaceIP:restPort]/QUEUE/Q/B
Solace REST messaging makes use of standard HTTP headers and introduces some custom headers specifically related to the Solace REST implementation. These headers do not determine where the message is routed but can determine other behavior related to the messaging. e.g. Setting the "Solace-DMQ-Eligible" header to true will allow for the message to be eligible to expire to the Dead Message Queue.
All headers are explained here: https://docs.solace.com/RESTMessagingPrtl/Solace-REST-Message-Encoding.htm#_Ref393979969
On the receiving end, a REST Delivery Point can be bound to one or more queues. Any messages delivered to these queues will be sent to the configured REST consumer.
Related
When subscribing to a wildcard and a topic that overlaps that wildcard, the client receives twice the messages because of this overlapping behavior.
Example:
Client-A:
subscribe{aaa/bbb/+/ddd, aaa/bbb/ccc/ddd}
Then, if I publish something on the wildcard topic, Client-A will receive only one:
Client-B:
Publish{aaa/bbb/www/ddd, "blablabla"}
Client-A:
Received{aaa/bbb/www/ddd, "blablabla"}
But, if I publish on the specific topic, Client-A receives twice:
Client-B:
Publish{aaa/bbb/ccc/ddd, "blablabla"}
Client-A:
Received{aaa/bbb/ccc/ddd, "blablabla"}
Received{aaa/bbb/ccc/ddd, "blablabla"}
Checking the MQTT specification, it states this (source, page 36, section 3.3.5 Actions):
When Clients make subscriptions with Topic Filters that include wildcards, it is possible for a Client’s subscriptions to overlap so that a published message might match multiple filters. In this case the Server MUST deliver the message to the Client respecting the maximum QoS of all the matching subscriptions [MQTT-3.3.5-1]. In addition, the Server MAY deliver further copies of the message, one for each additional matching subscription and respecting the subscription’s QoS in each case.
If I use the Paho MQTT-SN Gateway (Server), then the server sends only once. But if I use the Eclipse Public Server, then I receive twice. The behavior is not consistent, or, at least, I cannot expect which behavior will be until I test it.
The question is: is it possible to set the specific behavior for the wildcard overlap to send only once? Or it depends on server-to-server implementation?
As the specification says that either behaviour is correct it becomes a choice for the broker implementers and likewise adding a configuration option to change the behaviour one way or the other would be a choice.
You will have to test any broker you are using and then consult their documentation to see if it is possible to change the behaviour.
There is no generic answer to this question.
We have 2 different applications which interact with each by sending messages. Is it possible to have multiple listeners listening to the same queue. May be we could pass some header while pushing the message to the queue and then on the basis of header, the message would arrive in a single consumer.
No; RabbitMQ doesn't work that way; unlike JMS, there is no notion of a message selector.
Each consumer needs its own queue and you use a routing key to tell the broker which queue to route the message to.
I am using mosquitto mqtt client.
For example, you have users that publish and subscribe to topics. The topic actually correlates to a REsT endpoint.
Scenario 1 (typical pub/sub usage)
UserA subscribes to topic /device/123/meta
UserB publishes some data to topic /device/123/meta
by definition, this publish is broadcasted out to the subscribers
we have a script subscribed to /devices/# which knows how to save the payload for the topic /device/123/meta when it receives publish'ed data. This data is saved to the database.
Scenario 2
Someone updates data /device/123/meta via a ReST interface (or a direct DB update, the key is it's not a MQTT publish).
database is updated
a publish message is sent to the MQTT broker so that all subscribers get the updates as a payload
Scenario 2 is what I'm trying to wrap my head around. This creates a nasty feedback loop. When internal messages are broadcasted out, my script to deal with publish events from users can't differentiate between publish events originating from a 3rd party user or an internal publish event only meant to broadcast out some data (with no saving of data needed).
How should I handle this? The MQTT message is very simplistic and I'm not finding anything I can base logic off of. I'm trying to explore using the origin somehow, but no luck this far. I realize I can write plugins, but this is quite the task for mosquitto.
There is no way to distinguish where a message originated from the subscriber at a pure MQTT protocol level. Part of the point of a pub/sub protocol is to decouple publishers from subscribers.
The most portable way to do this would be to add a flag to the actual message payload to indicate that message originated from somewhere other than the actual device.
Or assuming the message is being published as a result a trigger in the database have the trigger check if the incoming message actually changed the database stored value, if the incoming messages matches the existing state of the DB then there is no need to republish it.
Mosquitto's plugin mechanism is currently only for writing authentication and authorisation solutions, but the JavaScript mosca or Java HiveMQ brokers support plugins that may be able to do what you want.
Is it possible to route message based on header to particular Queue in Solace Message Router ?
Please give brief details.
Solace Message Router routes messages via topics.
You can publish a message to either:
A topic (e.g. customer/uk/event/logon)
Directly into a queue (e.g. uk_Queue)
Queues on the Solace Message Router can be configured to receive one or more topics. For example, the uk_Queue can be configured to spool messages that were published to both customer/uk/event/logon and customer/uk/event/logoff.
You can add an egress selector to consumers that are bound to a queue. With the egress selector, only messages with headers that matches the selector string will be delivered to the consumers. Note that this only applies to delivery of messages to the consumers only. Messages that match the configured topics on the queue will be spooled regardless of whether or not the consumer's selectors match the messages.
Alternatively, you can create a topic endpoint, which allows ingress selectors. Topic endpoints will receive messages that match both the configurable topic and the header fields that matches the configured ingress selector.
You might also be interested in looking at
http://dev.solacesystems.com/get-started/java-tutorials/topic-queue-mapping_java/
which gives a brief introduction about topic to queue mappings.
I am looking for a solution to poll messages from MQTT broker. I will describe the solution briefly here.
We have a Spring based Controller class which exposes REST APIs to handle certain vehicle related diagnostics data. Through one of these API-s Notify3P() I create a MQTT java client and publish messages based on some input data to the MQTT broker on a given topic. My requirement is to notify a third-party system every time the client publishes a message on MQTT.
The 3P system is going to pick up the message from MQTT once it receives the notification. It then needs to get the message from the MQTT broker through a getMessage() REST API (which we need to expose on the above controller class). The getMessage() API needs to poll MQTT for the messages that have already been published and hand it to the 3P system. The 3P system would then do some processing and send back a response to our system through another REST API postMessage() exposed on our controller class. The postMessage() should post the message on the response topic on MQTT. I need another REST API checkResponse() which then polls the response topic of MQTT and send back the response to the client.
What I have done so far: On application start up I have a start up bean which listens to MQTT request and response topics. Now I publish data to request topic using the REST API Notify3P(). I have attached a callback with the startup bean which gets the message. The problem comes when the 3P needs to call my controller to poll message from MQTT.
I am not clear how to hold back messages on MQTT and consume it on demand. Is there a mechanism to do it in MQTT? Also once the 3P system post messages on the response then again how do I poll the response topic to pick up the response from MQTT and send to clients of my Controller?
I hope the problem description makes sense. If there is any solution from anyone please post it. Any sample code would of great help.
Thanks in advance!!
You may have got the idea of MQTT a bit confused. One of the key points is that there is no polling.
You subscribe to your response topic and publish to the request topic. As soon as a response is available you will be sent it by the broker. You can't hold back messages.
It sounds like your controller also needs to talk MQTT. If it is subscribed to the response topic from the start then it will receive the messages and you can do with them what you will, no need for polling.
To achieve exactly what you want, where the third party notifies the controller to read messages from MQTT then the controller would need to be able to use MQTT anyway. At that point you might as well do it "properly". If you don't want to integrate MQTT into your controller, then you can't do what you describe and you will have to come up with another means of communicating between the two components.
Summary - get your controller to talk MQTT if you can.