Skip to content

Commit 20736bd

Browse files
committed
Introduce acknowledgeAfterListener flag for custom acknowledge handling
Closes gh-34635
1 parent 37fb79e commit 20736bd

File tree

2 files changed

+56
-12
lines changed

2 files changed

+56
-12
lines changed

spring-jms/src/main/java/org/springframework/jms/config/AbstractJmsListenerContainerFactory.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -63,6 +63,9 @@ public abstract class AbstractJmsListenerContainerFactory<C extends AbstractMess
6363
@Nullable
6464
private Integer sessionAcknowledgeMode;
6565

66+
@Nullable
67+
private Boolean acknowledgeAfterListener;
68+
6669
@Nullable
6770
private Boolean pubSubDomain;
6871

@@ -141,6 +144,14 @@ public void setSessionAcknowledgeMode(Integer sessionAcknowledgeMode) {
141144
this.sessionAcknowledgeMode = sessionAcknowledgeMode;
142145
}
143146

147+
/**
148+
* @since 6.2.6
149+
* @see AbstractMessageListenerContainer#setAcknowledgeAfterListener(boolean)
150+
*/
151+
public void setAcknowledgeAfterListener(Boolean acknowledgeAfterListener) {
152+
this.acknowledgeAfterListener = acknowledgeAfterListener;
153+
}
154+
144155
/**
145156
* @see AbstractMessageListenerContainer#setPubSubDomain(boolean)
146157
*/
@@ -209,6 +220,7 @@ public void setObservationRegistry(ObservationRegistry observationRegistry) {
209220
this.observationRegistry = observationRegistry;
210221
}
211222

223+
212224
@Override
213225
public C createListenerContainer(JmsListenerEndpoint endpoint) {
214226
C instance = createContainerInstance();
@@ -234,6 +246,9 @@ public C createListenerContainer(JmsListenerEndpoint endpoint) {
234246
if (this.sessionAcknowledgeMode != null) {
235247
instance.setSessionAcknowledgeMode(this.sessionAcknowledgeMode);
236248
}
249+
if (this.acknowledgeAfterListener != null) {
250+
instance.setAcknowledgeAfterListener(this.acknowledgeAfterListener);
251+
}
237252
if (this.pubSubDomain != null) {
238253
instance.setPubSubDomain(this.pubSubDomain);
239254
}

spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java

+40-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -152,7 +152,8 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
152152
implements MessageListenerContainer {
153153

154154
private static final boolean micrometerJakartaPresent = ClassUtils.isPresent(
155-
"io.micrometer.jakarta9.instrument.jms.JmsInstrumentation", AbstractMessageListenerContainer.class.getClassLoader());
155+
"io.micrometer.jakarta9.instrument.jms.JmsInstrumentation",
156+
AbstractMessageListenerContainer.class.getClassLoader());
156157

157158
@Nullable
158159
private volatile Object destination;
@@ -170,14 +171,14 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
170171
@Nullable
171172
private String subscriptionName;
172173

174+
private boolean pubSubNoLocal = false;
175+
173176
@Nullable
174177
private Boolean replyPubSubDomain;
175178

176179
@Nullable
177180
private QosSettings replyQosSettings;
178181

179-
private boolean pubSubNoLocal = false;
180-
181182
@Nullable
182183
private MessageConverter messageConverter;
183184

@@ -190,6 +191,8 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
190191
@Nullable
191192
private ObservationRegistry observationRegistry;
192193

194+
private boolean acknowledgeAfterListener = true;
195+
193196
private boolean exposeListenerSession = true;
194197

195198
private boolean acceptMessagesWhileStopping = false;
@@ -500,12 +503,7 @@ public void setReplyPubSubDomain(boolean replyPubSubDomain) {
500503
*/
501504
@Override
502505
public boolean isReplyPubSubDomain() {
503-
if (this.replyPubSubDomain != null) {
504-
return this.replyPubSubDomain;
505-
}
506-
else {
507-
return isPubSubDomain();
508-
}
506+
return (this.replyPubSubDomain != null ? this.replyPubSubDomain : isPubSubDomain());
509507
}
510508

511509
/**
@@ -596,6 +594,37 @@ public ObservationRegistry getObservationRegistry() {
596594
return this.observationRegistry;
597595
}
598596

597+
/**
598+
* Specify whether the listener container should automatically acknowledge
599+
* each JMS Message after the message listener returned. This applies in
600+
* case of client acknowledge modes, including vendor-specific modes but
601+
* not in case of auto-acknowledge or a transacted JMS Session.
602+
* <p>As of 6.2, the default is {@code true}: The listener container will
603+
* acknowledge each JMS Message even in case of a vendor-specific mode,
604+
* assuming client-acknowledge style processing for custom vendor modes.
605+
* <p>If the provided listener prefers to manually acknowledge each message in
606+
* the listener itself, in combination with an "individual acknowledge" mode,
607+
* switch this flag to {code false} along with the vendor-specific mode.
608+
* @since 6.2.6
609+
* @see #setSessionAcknowledgeMode
610+
* @see #setMessageListener
611+
* @see Message#acknowledge()
612+
*/
613+
public void setAcknowledgeAfterListener(boolean acknowledgeAfterListener) {
614+
this.acknowledgeAfterListener = acknowledgeAfterListener;
615+
}
616+
617+
/**
618+
* Determine whether the listener container should automatically acknowledge
619+
* each JMS Message after the message listener returned.
620+
* @since 6.2.6
621+
* @see #setAcknowledgeAfterListener
622+
* @see #isClientAcknowledge(Session)
623+
*/
624+
public boolean isAcknowledgeAfterListener() {
625+
return this.acknowledgeAfterListener;
626+
}
627+
599628
/**
600629
* Set whether to expose the listener JMS Session to a registered
601630
* {@link SessionAwareMessageListener} as well as to
@@ -833,7 +862,7 @@ protected void commitIfNecessary(Session session, @Nullable Message message) thr
833862
JmsUtils.commitIfNecessary(session);
834863
}
835864
}
836-
else if (message != null && isClientAcknowledge(session)) {
865+
else if (message != null && isAcknowledgeAfterListener() && isClientAcknowledge(session)) {
837866
message.acknowledge();
838867
}
839868
}

0 commit comments

Comments
 (0)