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 https://github.com/spring-projects/spring-boot/issues/37447
Note that this PR depends on https://github.com/spring-projects/spring-boot/pull/37500 (which adds support for spring.jms.template.acknowledge-mode).
This PR also wraps up efforts started in https://github.com/spring-projects/spring-boot/pull/37473 that aim to improve developer experience when working with JMS vendors such as SQS, which provides non-standard acknowledge modes and doesn't support transactions
Comment From: wilkinsona
Thanks for the PR, @vpavic. I've rebased this on the latest change in main and tried adding a test:
@Test
void testJmsListenerContainerFactoryWithNonStandardAcknowledgeMode() {
this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class)
.withPropertyValues("spring.jms.listener.session.acknowledge-mode=9")
.run((context) -> {
DefaultMessageListenerContainer container = getContainer(context, "jmsListenerContainerFactory");
assertThat(container.getSessionAcknowledgeMode()).isEqualTo(9);
});
}
It fails:
java.lang.IllegalArgumentException: Only values of acknowledge mode constants allowed
at org.springframework.util.Assert.isTrue(Assert.java:111)
at org.springframework.jms.support.JmsAccessor.setSessionAcknowledgeMode(JmsAccessor.java:170)
at org.springframework.jms.config.AbstractJmsListenerContainerFactory.createListenerContainer(AbstractJmsListenerContainerFactory.java:235)
at org.springframework.boot.autoconfigure.jms.JmsAutoConfigurationTests.getContainer(JmsAutoConfigurationTests.java:271)
at org.springframework.boot.autoconfigure.jms.JmsAutoConfigurationTests.lambda$9(JmsAutoConfigurationTests.java:168)
at org.springframework.boot.test.context.runner.AbstractApplicationContextRunner.accept(AbstractApplicationContextRunner.java:434)
at org.springframework.boot.test.context.runner.AbstractApplicationContextRunner.consumeAssertableContext(AbstractApplicationContextRunner.java:363)
at org.springframework.boot.test.context.runner.AbstractApplicationContextRunner.lambda$1(AbstractApplicationContextRunner.java:341)
at org.springframework.boot.test.util.TestPropertyValues.lambda$5(TestPropertyValues.java:174)
at org.springframework.boot.test.util.TestPropertyValues.applyToSystemProperties(TestPropertyValues.java:188)
at org.springframework.boot.test.util.TestPropertyValues.applyToSystemProperties(TestPropertyValues.java:173)
at org.springframework.boot.test.context.runner.AbstractApplicationContextRunner.lambda$0(AbstractApplicationContextRunner.java:341)
at org.springframework.boot.test.context.runner.AbstractApplicationContextRunner.withContextClassLoader(AbstractApplicationContextRunner.java:369)
at org.springframework.boot.test.context.runner.AbstractApplicationContextRunner.run(AbstractApplicationContextRunner.java:340)
at org.springframework.boot.autoconfigure.jms.JmsAutoConfigurationTests.testJmsListenerContainerFactoryWithNonStandardAcknowledgeMode(JmsAutoConfigurationTests.java:167)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Apologies if I have introduced the problem while rebasing but I don't think I have. It looks to me like further Framework changes are required to support this.
Comment From: vpavic
After taking a quick look, it appears that this is caused by a regression in Spring Framework introduced in https://github.com/spring-projects/spring-framework/commit/3b8dd0a5acd9a6757d4849ccf2d5baf6c654ea57. Prior to that commit, JmsAccessor#setSessionAcknowledgeMode wasn't constrained to only standard acknowledge modes - I have several Spring Boot 3.1 based projects that are using SQSSession.UNORDERED_ACKNOWLEDGE.
I'll open an issue against Framework shortly.
Comment From: vpavic
Instead of an issue, I've opened https://github.com/spring-projects/spring-framework/pull/31328 to address the regression on the Framework side.
Comment From: vpavic
With https://github.com/spring-projects/spring-framework/pull/31328 merged, I assume this is now unblocked?
Comment From: wilkinsona
Not quite. We'll move to snapshots next week so it's blocked until then.
Comment From: vpavic
Is this expected to target 3.2? I'm asking because there's no assigned milestone.
Comment From: wilkinsona
Hopefully, yes, but we'll have to see what time permits. I'll assign it to 3.x for now and we can hopefully pull it forwards.
Comment From: wilkinsona
I've pushed my polishing: https://github.com/wilkinsona/spring-boot/tree/gh-37576.
However, I think we may need to take a different approach for a couple of reasons:
- By moving away from an enum, we've lost the capabilities of
LenientStringToEnumConverterFactory. This means that values likedupsokwill no longer work. - By doing the mapping when the property is used rather than when it's bound, the diagnostics won't be so good when the configuration is invalid
I'd like to discuss this with the rest of the team.