Spring WebSocket: Order of subscriptions don't allow messages to be received - java

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?

Related

How to send websocket message to a specific subscription in a session?

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.

How to get the QoS of a client in HiveMQ Client?

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.

Can two consumers get same set of messages while retrieving messages using an Pull based Manner?

So I have a one client-server based ecosystem where I am using RabbitMQ as a persistent Middleware.
Now the flow of a single message goes like this.
Step-1: Client A sends a message to the server with the destination
being set to Client B in the metadata of that message.
Step-2: Server upon receiving a message pushes the message to the
RabbitMQ and sends Client B a notification that he has some messages
to fetch.
Step-3: Client B upon getting notified calls the fetch message API to
get messages from the server.
Step-4: On the server, after getting called from the Client B pulls
messages from the RabbitMQ using the pull-based approach
(channel.basicGet(queueName, false)) and hands over the list of
messages.
Now in the above flow, there are few things that I have some doubt with.
First of all, if my client receives two notifications and calls the pull message API twice, there might be a concurrency problem.
Suppose I am not sending the message Acknowledgement while getting the message but I am sending afterwards, then can It be possible that the same message being sent to two pull API? If so is there any way to prevent this from happening?
Sample Code to Get Message From the MQ:
long currentMessageCount = channel.messageCount(QUEUE_NAME);
while (currentMessageCount-- > 0) {
GetResponse getResponse = channel.basicGet(QUEUE_NAME, false);
if (getResponse == null) {
break;
}
AMQP.BasicProperties props = getResponse.getProps();
Envelope envelope = getResponse.getEnvelope();
int messageCount = getResponse.getMessageCount();
byte[] body = getResponse.getBody();
/*
Do some logic
*/
channel.basicAck(envelope.getDeliveryTag(), false);
}
TIA
basicGet is rarely the correct solution. In Step 2, the client should be consuming from RabbitMQ. No notification that a message is ready is necessary. RabbitMQ will send the message to Client B as soon as it's in the queue. Step-3 and Step-4 become unnecessary.
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.

Firebase publisher subscriber

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.

Can we delay responding to a XMPP presence subscription?

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.

Categories

Resources