MESSAGE frames for a subscription can arrive after an UNSUBSCRIBE is sent (due to the basic asynchronous nature of the protocol), but then trying to ACK the MESSAGE received might fail because the subscription 'no longer exists'.
If the UNSUBSCRIBE id=foo is followed by SUBSCRIBE id=foo (allowed by the spec?) then it is still possible to receive a MESSAGE frame with the id=foo, but not to know for which subscription it is intended.
I propose that once a subscription id has been used in a session, it cannot be re-used in that session. This will mean that every MESSAGE frame received in that session has an unambiguous id reference. UNSUBSCRIBE will still have the force it has at present, it is just that it cannot guarantee that MESSAGE frames with that id will not subsequently be received.
What do you think?Hiram Chirino
Software Fellow | FuseSource Corp.
chi...@fusesource.com | fusesource.com
skype: hiramchirino | twitter: @hiramchirino
blog: Hiram Chirino's Bit Mojo

The UNSUBSCRIBE frame specification:TheUNSUBSCRIBEframe is used to remove an existing subscription. Once the subscription is removed the STOMP connections will no longer receive messages from that destination.This latter statement cannot be complied with unqualified because frames may 'cross in the post', as in my problem. A weaker guarantee could be asserted here, possibly referring to receipts, but see next.
The RECEIPT frame specification:Under 'Server Frames / RECEIPT' we read:ARECEIPTframe is sent from the server to the client once a server has has successfully processed a client frame that requests a receipt.Nowhere is "successfully processed" defined, but under 'Standard Headers / Header receipt' we read:Any client frame other thanCONNECTMAY specify areceiptheader with an arbitrary value. This will cause the server to acknowledge receipt of the frame with aRECEIPTframe which contains the value of this header as the value of thereceipt-idheader in theRECEIPTframe.Which implies that simple receipt is enough to trigger the RECEIPT frame. These two sections appear to be at odds.
For ACKs, we are following a convention that UNSUBSCRIBE implicitly NACKs any unacknowledged messages. This mirrors the behavior of ActiveMQ (where MessageConsumer.close implicitly NACKs messages which have not been acknowledged).
With the RECEIPT technique, this mechanism is not strictly necessary, and unless it is mandated in the STOMP spec, it would mean that clients wouldn't know if they can or cannot (N)ACK messages after UNSUBSCRIBE. So, I would only implement this technique if the spec said we must.
PS: I have just realised that (N)ACKs should not be issued for any MESSAGEs for a subscription which has been UNSUBSCRIBEd. This is to say that in the client frames, it is not allowed to refer to a subscription id in any frame after the UNSUBSCRIBE frame for that id has been sent.
along with the note that MESSAGE frames referring to old subscription ids can be received after sending an UNSUBSCRIBE, and that they cannot be ACKed or NACKed