Skip to content

Allow getting receipt from StompSession.Subscription.unsubscribe() #35224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Songdoeon
Copy link

Motivation

Currently Subscription.unsubscribe() is a void method, so clients have no way to know when an UNSUBSCRIBE frame has actually been processed by the server. This PR brings unsubscribe() in line with send() and acknowledge() by returning a Receiptable that callers can use to register callbacks and track the receipt.

Summary of Changes

  • Interface

    • StompSession.Subscription — both unsubscribe() overloads now return Receiptable instead of void.
  • Implementation

    • DefaultStompSession.unsubscribe(String, StompHeaders) (private helper) now returns a Receiptable by creating a ReceiptHandler after adding a receipt-id header.
    • DefaultStompSession.DefaultSubscription.unsubscribe(...) now invokes the helper and simply returns its Receiptable.
  • Tests (in DefaultStompSessionTests)

    • unsubscribeWithReceipt()
      Verifies that calling unsubscribe() returns a non‑null Receiptable and that the sent frame still only contains the subscription ID when auto‑receipt is off.
    • unsubscribeWithCustomHeaderAndReceipt()
      Verifies that with autoReceipt=true and custom headers, the UNSUBSCRIBE frame contains the subscription ID, the custom header, and the generated receipt header, and that the returned Receiptable holds the same receipt-id.
    • receiptReceivedOnUnsubscribe()
      Verifies that if a RECEIPT frame arrives for the receipt-id, a task registered on the returned Receiptable is executed.

All existing tests pass, and the new tests cover the added behavior.

Closes gh-22729

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jul 20, 2025
@Songdoeon Songdoeon force-pushed the issue/22729-unsubscribe-receiptable branch 2 times, most recently from 04bac3f to 39760ed Compare July 20, 2025 07:53
Copy link
Contributor

@rstoyanchev rstoyanchev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems reasonable to make this possible, but it could be an overloaded method, e.g. unsubsribeWithReceipt to make it optional to get a receipt.

@rstoyanchev rstoyanchev added in: messaging Issues in messaging modules (jms, messaging) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 7, 2025
@rstoyanchev rstoyanchev added this to the 7.0.x milestone Aug 7, 2025
@rstoyanchev rstoyanchev changed the title gh-22729: Make StompSession.Subscription.unsubscribe() return Receiptable Allow getting receipt from StompSession.Subscription.unsubscribe() Aug 7, 2025
@xak2000
Copy link
Contributor

xak2000 commented Aug 7, 2025

Hey, @rstoyanchev

It seems reasonable to make this possible, but it could be an overloaded method, e.g. unsubsribeWithReceipt to make it optional to get a receipt.

What is the motivation for adding a new method instead of using the existing unsubscribe?

I think using the existing method makes more sense because it will align with other methods (subscribe, send, acknowledge). All of them always return Receiptable even when setAutoReceipt is disabled or custom header do not contain the receipt-requesting header. We do not use subscribeWithRecepit or sendWithReceipt here, right?

Also, according to the setAutoReceipt docs subscribe and send automatically adds a receipt header if setAutoReceipt is enabled.

/**
* When enabled, a receipt header is automatically added to future
* {@code send} and {@code subscribe} operations on this session, which
* causes the server to return a RECEIPT. An application can then use
* the {@link StompSession.Receiptable Receiptable} returned from the
* operation to track the receipt.
* <p>A receipt header can also be added manually through the overloaded
* methods that accept {@code StompHeaders}.
*/
void setAutoReceipt(boolean enabled);

And I see the implementation in this PR uses the same logic: unsubscribe will automatically add a receipt header if setAutoReceipt is enabled.

Considering all of this I think it doesn't make sense to introduce a new overloaded method such as unsubsribeWithReceipt to make it optional to get a receipt. All other methods already return Receiptable and it is already optional for the caller to use the returned value or ignore it. Especially if setAutoReceipt is disabled and no receipt was sent in custom headers: in this case the returned Receiptable will not actually handle any recepits.

But I think the javadoc for setAutoReceipt could be improved. Currently the docs mention only send and subscribe methods, while in reality this flag also affects acknowledge and now will affect Subscription.unsubscribe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: messaging Issues in messaging modules (jms, messaging) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make StompSession.Subscription.unsubscribe() to return Receiptable
4 participants