Skip to content

Custom JMS acknowledgment and client acknowledgment auto-ack messages #32858

Closed as not planned
@Hanshiet

Description

@Hanshiet

When you configure a JMS listener with SessionAcknowledgeMode set to CLIENT_ACKNOWLEDGE or a custom mode like the UNORDERED_ACKNOWLEDGE mode of AWS SQS, messages are deleted from the SQS after receiving and processing them without a specific message.acknowledge() call.

After searching through debugging and the code, it seems that the problem lies in the combination of the commitIfNecessary function (located in spring-framework/spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java) and the isClientAcknowledge function (located in spring-framework/spring-jms/src/main/java/org/springframework/jms/support/JmsAccessor.java).

The isClientAcknowledge function was committed on 2023/06/12 with the following code:

protected boolean isClientAcknowledge(Session session) throws JMSException {
    int mode = session.getAcknowledgeMode();
    return (mode != Session.SESSION_TRANSACTED &&
            mode != Session.AUTO_ACKNOWLEDGE &&
            mode != Session.DUPS_OK_ACKNOWLEDGE);
}

And a specific message:

"This commit updates JmsAccessor to handle custom JMS acknowledgment modes as client acknowledge, which is useful when working with JMS providers that provide non-standard variations of CLIENT_ACKNOWLEDGE, such as AWS SQS and its UNORDERED_ACKNOWLEDGE mode."

However, commitIfNecessary, called always in the last line of doExecuteListener in the same class, commits the message with the condition "isClientAcknowledge(session)":

protected void commitIfNecessary(Session session, @Nullable Message message) throws JMSException {
    // Commit session or acknowledge message.
    if (session.getTransacted()) {
        // Commit necessary - but avoid commit call within a JTA transaction.
        if (isSessionLocallyTransacted(session)) {
            // Transacted session created by this container -> commit.
            JmsUtils.commitIfNecessary(session);
        }
    }
    else if (message != null && isClientAcknowledge(session)) {
        message.acknowledge();
    }
}

Is this correct? Commit should only be necessary in SESSION_TRANSACTED, AUTO_ACKNOWLEDGE, and DUPS_OK_ACKNOWLEDGE modes. Probably the correct condition is:

else if (message != null && !isClientAcknowledge(session))

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: messagingIssues in messaging modules (jms, messaging)status: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions