Add support for configuring non-standard JMS acknowledge modes

Prior to this commit, `spring.jms.listener.acknowledge-mode` and
`spring.jms.template.acknowledge-mode` accepted only a predefined set of
values representing standard JMS acknowledge modes.

This commit adds support for also using arbitrary integer values to
these configuration properties, which allow configuring vendor-specific
JMS acknowledge modes.

Closes gh-37447
pull/37576/head
Vedran Pavic 1 year ago
parent 5cfc198e6f
commit a1b49b298d

@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,6 +32,7 @@ import org.springframework.util.Assert;
*
* @author Stephane Nicoll
* @author Eddú Meléndez
* @author Vedran Pavic
* @since 1.3.3
*/
public final class DefaultJmsListenerContainerFactoryConfigurer {
@ -119,7 +120,7 @@ public final class DefaultJmsListenerContainerFactoryConfigurer {
JmsProperties.Listener listener = this.jmsProperties.getListener();
factory.setAutoStartup(listener.isAutoStartup());
if (listener.getAcknowledgeMode() != null) {
factory.setSessionAcknowledgeMode(listener.getAcknowledgeMode().getMode());
factory.setSessionAcknowledgeMode(JmsAcknowledgeModeMapper.map(listener.getAcknowledgeMode()));
}
String concurrency = listener.formatConcurrency();
if (concurrency != null) {

@ -0,0 +1,46 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.jms;
import java.util.HashMap;
import java.util.Map;
import jakarta.jms.Session;
/**
* Helper class used to map JMS acknowledge modes.
*
* @author Vedran Pavic
*/
final class JmsAcknowledgeModeMapper {
private static final Map<String, Integer> acknowledgeModes = new HashMap<>(3);
static {
acknowledgeModes.put("auto", Session.AUTO_ACKNOWLEDGE);
acknowledgeModes.put("client", Session.CLIENT_ACKNOWLEDGE);
acknowledgeModes.put("dups_ok", Session.DUPS_OK_ACKNOWLEDGE);
}
private JmsAcknowledgeModeMapper() {
}
static int map(String acknowledgeMode) {
return acknowledgeModes.computeIfAbsent(acknowledgeMode.toLowerCase(), Integer::parseInt);
}
}

@ -91,7 +91,8 @@ public class JmsAutoConfiguration {
PropertyMapper map = PropertyMapper.get();
map.from(properties::getAcknowledgeMode)
.whenNonNull()
.to((acknowledgeMode) -> template.setSessionAcknowledgeMode(acknowledgeMode.getMode()));
.to((acknowledgeMode) -> template
.setSessionAcknowledgeMode(JmsAcknowledgeModeMapper.map(acknowledgeMode)));
map.from(properties::getSessionTransacted).whenNonNull().to(template::setSessionTransacted);
map.from(properties::getDefaultDestination).whenNonNull().to(template::setDefaultDestinationName);
map.from(properties::getDeliveryDelay).whenNonNull().as(Duration::toMillis).to(template::setDeliveryDelay);

@ -145,7 +145,7 @@ public class JmsProperties {
* Acknowledge mode of the container. By default, the listener is transacted with
* automatic acknowledgment.
*/
private AcknowledgeMode acknowledgeMode;
private String acknowledgeMode;
/**
* Minimum number of concurrent consumers. When max-concurrency is not specified
@ -173,11 +173,11 @@ public class JmsProperties {
this.autoStartup = autoStartup;
}
public AcknowledgeMode getAcknowledgeMode() {
public String getAcknowledgeMode() {
return this.acknowledgeMode;
}
public void setAcknowledgeMode(AcknowledgeMode acknowledgeMode) {
public void setAcknowledgeMode(String acknowledgeMode) {
this.acknowledgeMode = acknowledgeMode;
}
@ -231,7 +231,7 @@ public class JmsProperties {
/**
* Acknowledgement mode used when creating JMS sessions to send a message.
*/
private AcknowledgeMode acknowledgeMode;
private String acknowledgeMode;
/**
* Whether to use transacted JMS sessions.
@ -278,11 +278,11 @@ public class JmsProperties {
*/
private Duration receiveTimeout;
public AcknowledgeMode getAcknowledgeMode() {
public String getAcknowledgeMode() {
return this.acknowledgeMode;
}
public void setAcknowledgeMode(AcknowledgeMode acknowledgeMode) {
public void setAcknowledgeMode(String acknowledgeMode) {
this.acknowledgeMode = acknowledgeMode;
}
@ -359,47 +359,6 @@ public class JmsProperties {
}
/**
* Translate the acknowledge modes defined on the {@link jakarta.jms.Session}.
*
* <p>
* {@link jakarta.jms.Session#SESSION_TRANSACTED} is not defined as we take care of
* this already through a call to {@code setSessionTransacted}.
*/
public enum AcknowledgeMode {
/**
* Messages sent or received from the session are automatically acknowledged. This
* is the simplest mode and enables once-only message delivery guarantee.
*/
AUTO(1),
/**
* Messages are acknowledged once the message listener implementation has called
* {@link jakarta.jms.Message#acknowledge()}. This mode gives the application
* (rather than the JMS provider) complete control over message acknowledgement.
*/
CLIENT(2),
/**
* Similar to auto acknowledgment except that said acknowledgment is lazy. As a
* consequence, the messages might be delivered more than once. This mode enables
* at-least-once message delivery guarantee.
*/
DUPS_OK(3);
private final int mode;
AcknowledgeMode(int mode) {
this.mode = mode;
}
public int getMode() {
return this.mode;
}
}
public enum DeliveryMode {
/**

@ -2987,6 +2987,40 @@
}
]
},
{
"name": "spring.jms.listener.acknowledge-mode",
"values": [
{
"value": "auto",
"description": "Messages sent or received from the session are automatically acknowledged. This is the simplest mode and enables once-only message delivery guarantee."
},
{
"value": "client",
"description": "Messages are acknowledged once the message listener implementation has called \"jakarta.jms.Message#acknowledge()\". This mode gives the application (rather than the JMS provider) complete control over message acknowledgement."
},
{
"value": "dups_ok",
"description": "Similar to auto acknowledgment except that said acknowledgment is lazy. As a consequence, the messages might be delivered more than once. This mode enables at-least-once message delivery guarantee."
}
]
},
{
"name": "spring.jms.template.acknowledge-mode",
"values": [
{
"value": "auto",
"description": "Messages sent or received from the session are automatically acknowledged. This is the simplest mode and enables once-only message delivery guarantee."
},
{
"value": "client",
"description": "Messages are acknowledged once the message listener implementation has called \"jakarta.jms.Message#acknowledge()\". This mode gives the application (rather than the JMS provider) complete control over message acknowledgement."
},
{
"value": "dups_ok",
"description": "Similar to auto acknowledgment except that said acknowledgment is lazy. As a consequence, the messages might be delivered more than once. This mode enables at-least-once message delivery guarantee."
}
]
},
{
"name": "spring.jmx.registration-policy",
"defaultValue": "fail-on-existing"

Loading…
Cancel
Save