I have implemented a WebSocket server using Spring WebSocket and STOMP. There are multiple subscriptions over a single session and I want to send message to a specific subscription only.
Steps to reproduce:
Client connects to server by calling registered STOMP endpoint.
Client makes 2 subscription over the connection.
SUBSCRIBE
country:germany
id:sub-0
destination:/user/queue/countryUpdates
SUBSCRIBE
country:france
id:sub-1
destination:/user/queue/countryUpdates
In SimpUserRegistry there is 1 user and 1 session with 2 subscription.
Problem is if I send a message to one subscription it's send to other subscription as well.
At the time of sending the message I am adding subscription id in native headers, but it's not working.
SimpMessageHeaderAccessor accessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
accessor.setNativeHeader("id", subscriptionId);
accessor.setNativeHeader("subscription", subscriptionId);
accessor.setSubscriptionId(subscriptionId);
accessor.setLeaveMutable(true);
messagingTemplate.convertAndSendToUser(simpUserId, REPLY_DESTINATION, message, accessor.getMessageHeaders());
What I've tried: If I add country to destination, each subscription have unique destination than there are no duplicate messages.
I want to use id/subscriptionId to determine the subscription and send message to that particular subscription.
Related
I followed the https://spring.io/guides/gs/messaging-stomp-websocket/ and added a few modifications (mainly Spring Security Auth and dynamic topics(Rooms)).
The order the client subscribes to topics doesn't allow messages onDisconnect event to be received by the client that's still in the room despite the server sysout showing that it sends.
I have 2 topics that the client subscribes to in a room and this order of subscriptions works but if I change the order of the subscriptions then the user that's still in the room won't receive a message:
// user direct message
stompClient.subscribe(`/user/topic/${roomId}`, (message) => {...}
// General
stompClient.subscribe(`/topic/${roomId}`, (message) => {...}
2 users connect and I send alerts to the client that the users joined and all is well until 1 client disconnects. In the order of subscriptions above the client that's still in the room will receive the message that a client has disconnected but if the subscription order is changed then the client will not receive the message that a client disconnected.
Does the order in how the client subscribes to topics matter?
I'm working with HiveMQ Client and I wanted to know if there was a way to get the quality of service (QoS) that a client is subscribing with (in terms of a specific topic or in general)? I would be looking for a method I could invoke on a client like so:
Mqtt5BlockingClient subscriber = Mqtt5Client.builder()
.identifier(UUID.randomUUID().toString()) // the unique identifier of the MQTT client
.serverHost("localhost")
.serverPort(1883)
.buildBlocking();
subscriber.getQoS("topic") // returns the QoS of the subscriber is subscribing to the given topic
I would just want this information so I could print in to the console.
I think you have to read more about MQTT concepts.
The Quality of Service (QoS) level is an agreement between a sender and receiver of a message regarding the guarantees of delivering a message.
Therefore, the QoS is used in the publish() and subscribe() methods not the connect().
This is the scenario:
1. Connect: You have to connect your client to any broker with username/password. Every mqtt library has a connect() method. In this step, you have not specified qos yet.
After successful connection (every mqtt library has a callback for the connect method) and you can publish or subscribe to any desired (or allowed) topics.
Example:
Eclipse Paho library:
IMqttToken token = clientPhone.connect();
HiveMQ Library:
client.connect();
//or
client.connectWith().keepAlive(10).send();
//or
Mqtt5Connect connectMessage = Mqtt5Connect.builder().keepAlive(10).build();
client.connect(connectMessage);
2. Publish:
When you want to publish() a message, you have to specify a qos, so that the broker will respond to the client according with this qos:
Qos=0:
Client ---- Publish method ----> broker
Qos=1:
Client ---- Publish method ----> broker
Client <---- PubAck callback ---- broker
Qos=2:
Client ---- Publish method ----> broker
Client <---- PubRec callback ---- broker
Client ---- PubRel method ----> broker
Client <---- PubComp callback ---- broker
Example:
Eclipse Paho library:
IMqttDeliveryToken tokenPub = clientPhone.publish(topicPub, message);
HiveMQ Library:
client.publishWith()
.topic("test/topic")
.qos(MqttQos.AT_LEAST_ONCE)
.payload("payload".getBytes())
.send();
//or:
Mqtt5Publish publishMessage = Mqtt5Publish.builder()
.topic("test/topic")
.qos(MqttQos.AT_LEAST_ONCE)
.payload("payload".getBytes())
.build();
client.publish(publishMessage);
3. Subscribe:
A SUBSCRIBE message can contain an arbitrary number of subscriptions for a client. Each subscription is a pair of a topic and QoS level. The topic in the subscribe message can also contain wildcards, which makes it possible to subscribe to certain topic patterns. If there are overlapping subscriptions for one client, the highest QoS level for that topic wins and will be used by the broker for delivering the message.
Example:
Eclipse Paho library:
IMqttToken subToken = MqttAndroidClientInstance.subscribe(topics, qos);
HiveMQ Library:
client.subscribeWith().topicFilter("test/topic").qos(MqttQos.EXACTLY_ONCE).send();
//or:
Mqtt5Subscribe subscribeMessage = Mqtt5Subscribe.builder()
.topicFilter("test/topic")
.qos(MqttQos.EXACTLY_ONCE)
.build();
client.subscribe(subscribeMessage);
Edit(1):
A mqtt client have to use the following parameters, if wants to receive the already subscribed topics after reconnecting:
A- connect with cleanSession false.
B- Subscribe with QOS>0.
I'm new to RabbitMQ and want to implement asynchronous messaging of SAGA with RabbitMQ.So I used RPC example of RabbitMQ to do the task. I've one orchestrator ( RPCClient) and multiple microservices ( RPCServer). Orchestrator uses unique queues to command microservices.And each microservice uses a common queue ( Reply_ Queue) to reply orchestrator. To keep log I want to get notifications in orchestrator side, when any microservice is down for any configurable time.
I read about consumer cancellation,but it only works when I delete the queue.How to get notifications in JAVA with keeping queue messages? And is it correct way to implement saga asynchronous messaging?
To implement a reliable RPC is hard, I can't give a detail guide about how to do this. If we ignore same special failure situation, I can give a simple workaround:
First, we assume that RPCClient never fail, RPCServer may fail anytime.
RPCClient need to know which request is timeout, so it can send request message with a TTL. After RPCServer receive request message and send response message, it should ACK the request message.
If RPCServer:
has failed before consume request message
OR
has failed before send response message
The request message will be republish to Dead Letter Exchange, so RPCClient can consume to some queue binded with that exchange, it can know which request is timeout.
Firebase If subscriber is subscribed to a topic before publisher subscribes and pushes to the topic , can Firebase deliver message to subscriber after publisher pushes message ?
In my app I have a scenario where if subscriber subscribes to a topic first before publisher adds to that topic and sends message , I should be able to send that message to initially added subscriber.
If i understand well your request, according to the documentation, the messages sent to a topic are received only after the device has suscribed. So, it doesn't receive messages that were sent to the topic when it isn't subscribed.
Also:
Client apps can subscribe to any existing topic, or they can create a
new topic. When a client app subscribes to a new topic name (one that
does not already exist for your Firebase project), a new topic of that
name is created in FCM and any client can subsequently subscribe to
it.
I am using a PacketListener to receive XMPP packets.
If I receive the following:
<presence from="jeanne#belle.com" to="betty#belle.com" type="subscribe"/>
is the XMPP server expecting me to respond immediately ?
Motivation: I want to cache all these subscription requests and allow the recipient to selectively ACCEPT/DENY (à la facebook invitations).
Is there an API in which I can request for all subscription requests from openfire ?
You do NOT need to reply immediately or even in a given session; the server stores the fact that you have a pending inbound subscription, and will re-inform you of the pending subscription every time you log in. Therefore, there should be no need to request the list either.