Search code examples
iosswiftactivemq-classicswift4stomp

StompClientLib - unsubscribe socketclient


I've added StompClientLib in my project and I'm facing problem while unsubscribing a destination topic.

Unsubscription of destination gives following error: "org.apache.activemq.transport.stomp.ProtocolException: No subscription matched.\r\tat org.apache.activemq.transport.stomp.ProtocolConverter.onStompUnsubscribe(ProtocolConverter.java:734)\r\tat org.apache.activemq.transport.stomp.ProtocolConverter.onStompCommand(ProtocolConverter.java:262)\r\tat org.apache.activemq.transport.ws.AbstractStompSocket.processStompFrame(AbstractStompSocket.java:151)\r\tat org.apache.activemq.transport.ws.jetty9.StompSocket.onWebSocketText(StompSocket.java:96)\r\tat org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver.onTextMessage(JettyListenerEventDriver.java:128)\r\tat org.eclipse.jetty.websocket.common.message.SimpleTextMessage.messageComplete(SimpleTextMessage.java:69)\r\tat org.eclipse.jetty.websocket.common.events.AbstractEventDriver.appendMessage(AbstractEventDriver.java:64)\r\tat org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver.onTextFrame(JettyListenerEventDriver.java:122)\r\tat org.eclipse.jetty.websocket.common.events.AbstractEventDriver.incomingFrame(AbstractEventDriver.java:160)\r\tat org.eclipse.jetty.websocket.common.WebSocketSession.incomingFrame(WebSocketSession.java:309)\r\tat org.eclipse.jetty.websocket.common.extensions.ExtensionStack.incomingFrame(ExtensionStack.java:214)\r\tat org.eclipse.jetty.websocket.common.Parser.notifyFrame(Parser.java:220)\r\tat org.eclipse.jetty.websocket.common.Parser.parse(Parser.java:258)\r\tat org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.readParse(AbstractWebSocketConnection.java:628)\r\tat org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:476)\r\tat org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)\r\tat org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)\r\tat org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)\r\tat java.lang.Thread.run(Unknown Source)\r")

Yes, It's an issue with subscription name but It doesn't accept the same string I used to subscribe specific channel.

For example:

```
// destination
let destinationChannelTopic = "/topic/channel_1234"

// subscribe successful
socketClient?.subscribe(destination: destinationChannelTopic)

// unsubscribe not successful with same destination
socketClient?.unsubscribe(destination: destinationChannelTopic)
```

Here unsubscribe replies me with an error: No subscription matched
Can anyone help me to understand, what is wrong? What am I doing wrong?

As I analyzed from Subscribe and receive messages, subscription (a subscribe method) returns a string (subscription channel id) from the server, that we need to store somewhere at client side (in our project/code) and we need to use the same string to unsubscribe.

This is javcScript (not an iOS - swift) code, a sample that available in this link (Subscribe and receive messages) and we implemented similar way it in web application:

```
// subscribe
var subscription = client.subscribe("/queue/test", callback);
```

The subscribe() methods return a JavaScript object with 1 attribute, id, that correspond to the client subscription ID and one method unsubscribe() that can be used later on to unsubscribe the client from this destination.

```
// unsubscribe
subscription.unsubscribe();
```

So, is this only the method/possible way, for subscription and unsubscription. If yes, then we do not have any value returning to subscribe(...) that I can use to unsubscribe. I don't get any value (destination subscription id) from subscription socketClient?.subscribe(destination: destinationChannelTopic) method

As an alternate solution to this issue, I disconnect the client from the server and reconnect again + subscribe to all other destinations again. And this is not a proper way to handle but I have only this solution at this time.

Please help to find out the solution for this problem.

Here is reference link about the issue: unsubscribe socketclient #14


Solution

  • Subscription methodology approach for subscribe and unsubscribe are very different.

    Subscribe uses unique destination (id) to connect with server as a destination but links and remembers it with reference of subscription-id and uses subscription-id to identify itself on server while unsubcribe.

    Here is code, you are looking for. Try it.

    let destination = "/topic/channel_1234"
    let ack = "ack_\(destination)" // It can be any unique string
    let subsId = "subscription_\(destination)" // It can be any unique string
    let header = ["destination": destination, "ack": ack, "id": subsId]
    
    // subscribe
    socketClient?.subscribeWithHeader(destination: destination, withHeader: header)
    
    // unsubscribe
    socketClient?.unsubscribe(destination: subsId)