Add support for JmsClient
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run CodeQL Analysis / run-analysis (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run CodeQL Analysis / run-analysis (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
This commits adds auto-configuration for the new JmsClient API introduced in Spring Framework 7. JmsClient is auto-configured the same way as JmsTemplate and uses it behind the scenes. Closes gh-46293
This commit is contained in:
parent
870e652e85
commit
626065a827
|
@ -35,7 +35,7 @@ import org.springframework.boot.testsupport.container.TestImage;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.jms.annotation.JmsListener;
|
import org.springframework.jms.annotation.JmsListener;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -54,14 +54,14 @@ class ActiveMQClassicContainerConnectionDetailsFactoryIntegrationTests {
|
||||||
static final ActiveMQContainer activemq = TestImage.container(ActiveMQContainer.class);
|
static final ActiveMQContainer activemq = TestImage.container(ActiveMQContainer.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JmsMessagingTemplate jmsTemplate;
|
private JmsClient jmsClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TestListener listener;
|
private TestListener listener;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void connectionCanBeMadeToActiveMQContainer() {
|
void connectionCanBeMadeToActiveMQContainer() {
|
||||||
this.jmsTemplate.convertAndSend("sample.queue", "message");
|
this.jmsClient.destination("sample.queue").send("message");
|
||||||
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
||||||
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.springframework.boot.testsupport.container.TestImage;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.jms.annotation.JmsListener;
|
import org.springframework.jms.annotation.JmsListener;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -54,14 +54,14 @@ class ActiveMQContainerConnectionDetailsFactoryIntegrationTests {
|
||||||
static final SymptomaActiveMQContainer activemq = TestImage.container(SymptomaActiveMQContainer.class);
|
static final SymptomaActiveMQContainer activemq = TestImage.container(SymptomaActiveMQContainer.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JmsMessagingTemplate jmsTemplate;
|
private JmsClient jmsClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TestListener listener;
|
private TestListener listener;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void connectionCanBeMadeToActiveMQContainer() {
|
void connectionCanBeMadeToActiveMQContainer() {
|
||||||
this.jmsTemplate.convertAndSend("sample.queue", "message");
|
this.jmsClient.destination("sample.queue").send("message");
|
||||||
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
||||||
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.springframework.boot.testsupport.container.TestImage;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.jms.annotation.JmsListener;
|
import org.springframework.jms.annotation.JmsListener;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -54,14 +54,14 @@ class ArtemisContainerConnectionDetailsFactoryIntegrationTests {
|
||||||
static final ArtemisContainer artemis = TestImage.container(ArtemisContainer.class);
|
static final ArtemisContainer artemis = TestImage.container(ArtemisContainer.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JmsMessagingTemplate jmsTemplate;
|
private JmsClient jmsClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TestListener listener;
|
private TestListener listener;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void connectionCanBeMadeToActiveMQContainer() {
|
void connectionCanBeMadeToActiveMQContainer() {
|
||||||
this.jmsTemplate.convertAndSend("sample.queue", "message");
|
this.jmsClient.destination("sample.queue").send("message");
|
||||||
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
||||||
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -725,6 +725,7 @@ Auto-configuration enables the instrumentation of all available javadoc:org.spri
|
||||||
This will produce `"jms.message.publish"` and `"jms.message.process"` metrics respectively.
|
This will produce `"jms.message.publish"` and `"jms.message.process"` metrics respectively.
|
||||||
See the {url-spring-framework-docs}/integration/observability.html#observability.jms[Spring Framework reference documentation for more information on produced observations].
|
See the {url-spring-framework-docs}/integration/observability.html#observability.jms[Spring Framework reference documentation for more information on produced observations].
|
||||||
|
|
||||||
|
NOTE: javadoc:org.springframework.jms.core.JmsClient[] and javadoc:org.springframework.jms.core.JmsMessagingTemplate[] that uses a javadoc:org.springframework.jms.core.JmsTemplate[] bean are also instrumented.
|
||||||
|
|
||||||
|
|
||||||
[[actuator.metrics.supported.spring-mvc]]
|
[[actuator.metrics.supported.spring-mvc]]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[[messaging]]
|
[[messaging]]
|
||||||
= Messaging
|
= Messaging
|
||||||
|
|
||||||
The Spring Framework provides extensive support for integrating with messaging systems, from simplified use of the JMS API using javadoc:org.springframework.jms.core.JmsTemplate[] to a complete infrastructure to receive messages asynchronously.
|
The Spring Framework provides extensive support for integrating with messaging systems, from simplified use of the JMS API using javadoc:org.springframework.jms.core.JmsClient[] to a complete infrastructure to receive messages asynchronously.
|
||||||
Spring AMQP provides a similar feature set for the Advanced Message Queuing Protocol.
|
Spring AMQP provides a similar feature set for the Advanced Message Queuing Protocol.
|
||||||
Spring Boot also provides auto-configuration options for javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[] and RabbitMQ.
|
Spring Boot also provides auto-configuration options for javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[] and RabbitMQ.
|
||||||
Spring WebSocket natively includes support for STOMP messaging, and Spring Boot has support for that through starters and a small amount of auto-configuration.
|
Spring WebSocket natively includes support for STOMP messaging, and Spring Boot has support for that through starters and a small amount of auto-configuration.
|
||||||
|
|
|
@ -145,11 +145,11 @@ spring:
|
||||||
[[messaging.jms.sending]]
|
[[messaging.jms.sending]]
|
||||||
== Sending a Message
|
== Sending a Message
|
||||||
|
|
||||||
Spring's javadoc:org.springframework.jms.core.JmsTemplate[] is auto-configured, and you can autowire it directly into your own beans, as shown in the following example:
|
Spring's javadoc:org.springframework.jms.core.JmsClient[] is auto-configured, and you can autowire it directly into your own beans, as shown in the following example:
|
||||||
|
|
||||||
include-code::MyBean[]
|
include-code::MyBean[]
|
||||||
|
|
||||||
NOTE: javadoc:org.springframework.jms.core.JmsMessagingTemplate[] can be injected in a similar manner.
|
NOTE: javadoc:org.springframework.jms.core.JmsMessagingTemplate[] can be injected in a similar manner, and both use the traditional javadoc:org.springframework.jms.core.JmsTemplate[] that can be injected as well.
|
||||||
If a javadoc:org.springframework.jms.support.destination.DestinationResolver[] or a javadoc:org.springframework.jms.support.converter.MessageConverter[] bean is defined, it is associated automatically to the auto-configured javadoc:org.springframework.jms.core.JmsTemplate[].
|
If a javadoc:org.springframework.jms.support.destination.DestinationResolver[] or a javadoc:org.springframework.jms.support.converter.MessageConverter[] bean is defined, it is associated automatically to the auto-configured javadoc:org.springframework.jms.core.JmsTemplate[].
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,21 +16,21 @@
|
||||||
|
|
||||||
package org.springframework.boot.docs.messaging.jms.sending;
|
package org.springframework.boot.docs.messaging.jms.sending;
|
||||||
|
|
||||||
import org.springframework.jms.core.JmsTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class MyBean {
|
public class MyBean {
|
||||||
|
|
||||||
private final JmsTemplate jmsTemplate;
|
private final JmsClient jmsClient;
|
||||||
|
|
||||||
public MyBean(JmsTemplate jmsTemplate) {
|
public MyBean(JmsClient jmsClient) {
|
||||||
this.jmsTemplate = jmsTemplate;
|
this.jmsClient = jmsClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @fold:on // ...
|
// @fold:on // ...
|
||||||
public void someMethod() {
|
public void someMethod() {
|
||||||
this.jmsTemplate.convertAndSend("hello");
|
this.jmsClient.destination("myQueue").send("hello");
|
||||||
}
|
}
|
||||||
// @fold:off
|
// @fold:off
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
|
|
||||||
package org.springframework.boot.docs.messaging.jms.sending
|
package org.springframework.boot.docs.messaging.jms.sending
|
||||||
|
|
||||||
import org.springframework.jms.core.JmsTemplate
|
import org.springframework.jms.core.JmsClient
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class MyBean(private val jmsTemplate: JmsTemplate) {
|
class MyBean(private val jmsClient: JmsClient) {
|
||||||
|
|
||||||
// @fold:on // ...
|
// @fold:on // ...
|
||||||
fun someMethod() {
|
fun someMethod() {
|
||||||
jmsTemplate.convertAndSend("hello")
|
jmsClient.destination("myQueue").send("hello")
|
||||||
}
|
}
|
||||||
// @fold:off
|
// @fold:off
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.jms.autoconfigure;
|
package org.springframework.boot.jms.autoconfigure;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
|
||||||
import jakarta.jms.ConnectionFactory;
|
import jakarta.jms.ConnectionFactory;
|
||||||
import jakarta.jms.Message;
|
import jakarta.jms.Message;
|
||||||
|
|
||||||
|
@ -27,28 +25,15 @@ import org.springframework.aot.hint.ExecutableMode;
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||||
import org.springframework.aot.hint.TypeReference;
|
import org.springframework.aot.hint.TypeReference;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.context.properties.PropertyMapper;
|
|
||||||
import org.springframework.boot.jms.autoconfigure.JmsAutoConfiguration.JmsRuntimeHints;
|
import org.springframework.boot.jms.autoconfigure.JmsAutoConfiguration.JmsRuntimeHints;
|
||||||
import org.springframework.boot.jms.autoconfigure.JmsProperties.DeliveryMode;
|
|
||||||
import org.springframework.boot.jms.autoconfigure.JmsProperties.Template;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||||
import org.springframework.jms.core.JmsMessageOperations;
|
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
|
||||||
import org.springframework.jms.core.JmsOperations;
|
|
||||||
import org.springframework.jms.core.JmsTemplate;
|
import org.springframework.jms.core.JmsTemplate;
|
||||||
import org.springframework.jms.support.converter.MessageConverter;
|
|
||||||
import org.springframework.jms.support.destination.DestinationResolver;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring JMS.
|
* {@link EnableAutoConfiguration Auto-configuration} for Spring JMS.
|
||||||
|
@ -62,81 +47,12 @@ import org.springframework.jms.support.destination.DestinationResolver;
|
||||||
@ConditionalOnClass({ Message.class, JmsTemplate.class })
|
@ConditionalOnClass({ Message.class, JmsTemplate.class })
|
||||||
@ConditionalOnBean(ConnectionFactory.class)
|
@ConditionalOnBean(ConnectionFactory.class)
|
||||||
@EnableConfigurationProperties(JmsProperties.class)
|
@EnableConfigurationProperties(JmsProperties.class)
|
||||||
@Import(JmsAnnotationDrivenConfiguration.class)
|
@Import({ JmsClientConfigurations.JmsTemplateConfiguration.class,
|
||||||
|
JmsClientConfigurations.MessagingTemplateConfiguration.class,
|
||||||
|
JmsClientConfigurations.JmsClientConfiguration.class, JmsAnnotationDrivenConfiguration.class })
|
||||||
@ImportRuntimeHints(JmsRuntimeHints.class)
|
@ImportRuntimeHints(JmsRuntimeHints.class)
|
||||||
public class JmsAutoConfiguration {
|
public class JmsAutoConfiguration {
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
protected static class JmsTemplateConfiguration {
|
|
||||||
|
|
||||||
private final JmsProperties properties;
|
|
||||||
|
|
||||||
private final ObjectProvider<DestinationResolver> destinationResolver;
|
|
||||||
|
|
||||||
private final ObjectProvider<MessageConverter> messageConverter;
|
|
||||||
|
|
||||||
private final ObjectProvider<ObservationRegistry> observationRegistry;
|
|
||||||
|
|
||||||
public JmsTemplateConfiguration(JmsProperties properties,
|
|
||||||
ObjectProvider<DestinationResolver> destinationResolver,
|
|
||||||
ObjectProvider<MessageConverter> messageConverter,
|
|
||||||
ObjectProvider<ObservationRegistry> observationRegistry) {
|
|
||||||
this.properties = properties;
|
|
||||||
this.destinationResolver = destinationResolver;
|
|
||||||
this.messageConverter = messageConverter;
|
|
||||||
this.observationRegistry = observationRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(JmsOperations.class)
|
|
||||||
@ConditionalOnSingleCandidate(ConnectionFactory.class)
|
|
||||||
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
|
|
||||||
PropertyMapper map = PropertyMapper.get();
|
|
||||||
JmsTemplate template = new JmsTemplate(connectionFactory);
|
|
||||||
template.setPubSubDomain(this.properties.isPubSubDomain());
|
|
||||||
map.from(this.destinationResolver::getIfUnique).whenNonNull().to(template::setDestinationResolver);
|
|
||||||
map.from(this.messageConverter::getIfUnique).whenNonNull().to(template::setMessageConverter);
|
|
||||||
map.from(this.observationRegistry::getIfUnique).whenNonNull().to(template::setObservationRegistry);
|
|
||||||
mapTemplateProperties(this.properties.getTemplate(), template);
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mapTemplateProperties(Template properties, JmsTemplate template) {
|
|
||||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
|
||||||
map.from(properties.getSession().getAcknowledgeMode()::getMode).to(template::setSessionAcknowledgeMode);
|
|
||||||
map.from(properties.getSession()::isTransacted).to(template::setSessionTransacted);
|
|
||||||
map.from(properties::getDefaultDestination).whenNonNull().to(template::setDefaultDestinationName);
|
|
||||||
map.from(properties::getDeliveryDelay).whenNonNull().as(Duration::toMillis).to(template::setDeliveryDelay);
|
|
||||||
map.from(properties::determineQosEnabled).to(template::setExplicitQosEnabled);
|
|
||||||
map.from(properties::getDeliveryMode).as(DeliveryMode::getValue).to(template::setDeliveryMode);
|
|
||||||
map.from(properties::getPriority).whenNonNull().to(template::setPriority);
|
|
||||||
map.from(properties::getTimeToLive).whenNonNull().as(Duration::toMillis).to(template::setTimeToLive);
|
|
||||||
map.from(properties::getReceiveTimeout).as(Duration::toMillis).to(template::setReceiveTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnClass(JmsMessagingTemplate.class)
|
|
||||||
@Import(JmsTemplateConfiguration.class)
|
|
||||||
protected static class MessagingTemplateConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(JmsMessageOperations.class)
|
|
||||||
@ConditionalOnSingleCandidate(JmsTemplate.class)
|
|
||||||
public JmsMessagingTemplate jmsMessagingTemplate(JmsProperties properties, JmsTemplate jmsTemplate) {
|
|
||||||
JmsMessagingTemplate messagingTemplate = new JmsMessagingTemplate(jmsTemplate);
|
|
||||||
mapTemplateProperties(properties.getTemplate(), messagingTemplate);
|
|
||||||
return messagingTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mapTemplateProperties(Template properties, JmsMessagingTemplate messagingTemplate) {
|
|
||||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
|
||||||
map.from(properties::getDefaultDestination).to(messagingTemplate::setDefaultDestinationName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class JmsRuntimeHints implements RuntimeHintsRegistrar {
|
static class JmsRuntimeHints implements RuntimeHintsRegistrar {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.jms.autoconfigure;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
|
import jakarta.jms.ConnectionFactory;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||||
|
import org.springframework.boot.context.properties.PropertyMapper;
|
||||||
|
import org.springframework.boot.jms.autoconfigure.JmsProperties.DeliveryMode;
|
||||||
|
import org.springframework.boot.jms.autoconfigure.JmsProperties.Template;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.jms.core.JmsClient;
|
||||||
|
import org.springframework.jms.core.JmsMessageOperations;
|
||||||
|
import org.springframework.jms.core.JmsMessagingTemplate;
|
||||||
|
import org.springframework.jms.core.JmsOperations;
|
||||||
|
import org.springframework.jms.core.JmsTemplate;
|
||||||
|
import org.springframework.jms.support.converter.MessageConverter;
|
||||||
|
import org.springframework.jms.support.destination.DestinationResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurations for JMS client infrastructure.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @see JmsAutoConfiguration
|
||||||
|
*/
|
||||||
|
abstract class JmsClientConfigurations {
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class JmsTemplateConfiguration {
|
||||||
|
|
||||||
|
private final JmsProperties properties;
|
||||||
|
|
||||||
|
private final ObjectProvider<DestinationResolver> destinationResolver;
|
||||||
|
|
||||||
|
private final ObjectProvider<MessageConverter> messageConverter;
|
||||||
|
|
||||||
|
private final ObjectProvider<ObservationRegistry> observationRegistry;
|
||||||
|
|
||||||
|
JmsTemplateConfiguration(JmsProperties properties, ObjectProvider<DestinationResolver> destinationResolver,
|
||||||
|
ObjectProvider<MessageConverter> messageConverter,
|
||||||
|
ObjectProvider<ObservationRegistry> observationRegistry) {
|
||||||
|
this.properties = properties;
|
||||||
|
this.destinationResolver = destinationResolver;
|
||||||
|
this.messageConverter = messageConverter;
|
||||||
|
this.observationRegistry = observationRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(JmsOperations.class)
|
||||||
|
@ConditionalOnSingleCandidate(ConnectionFactory.class)
|
||||||
|
JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
|
||||||
|
PropertyMapper map = PropertyMapper.get();
|
||||||
|
JmsTemplate template = new JmsTemplate(connectionFactory);
|
||||||
|
template.setPubSubDomain(this.properties.isPubSubDomain());
|
||||||
|
map.from(this.destinationResolver::getIfUnique).whenNonNull().to(template::setDestinationResolver);
|
||||||
|
map.from(this.messageConverter::getIfUnique).whenNonNull().to(template::setMessageConverter);
|
||||||
|
map.from(this.observationRegistry::getIfUnique).whenNonNull().to(template::setObservationRegistry);
|
||||||
|
mapTemplateProperties(this.properties.getTemplate(), template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mapTemplateProperties(Template properties, JmsTemplate template) {
|
||||||
|
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||||
|
map.from(properties.getSession().getAcknowledgeMode()::getMode).to(template::setSessionAcknowledgeMode);
|
||||||
|
map.from(properties.getSession()::isTransacted).to(template::setSessionTransacted);
|
||||||
|
map.from(properties::getDefaultDestination).whenNonNull().to(template::setDefaultDestinationName);
|
||||||
|
map.from(properties::getDeliveryDelay).whenNonNull().as(Duration::toMillis).to(template::setDeliveryDelay);
|
||||||
|
map.from(properties::determineQosEnabled).to(template::setExplicitQosEnabled);
|
||||||
|
map.from(properties::getDeliveryMode).as(DeliveryMode::getValue).to(template::setDeliveryMode);
|
||||||
|
map.from(properties::getPriority).whenNonNull().to(template::setPriority);
|
||||||
|
map.from(properties::getTimeToLive).whenNonNull().as(Duration::toMillis).to(template::setTimeToLive);
|
||||||
|
map.from(properties::getReceiveTimeout).as(Duration::toMillis).to(template::setReceiveTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(JmsMessagingTemplate.class)
|
||||||
|
static class MessagingTemplateConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(JmsMessageOperations.class)
|
||||||
|
@ConditionalOnSingleCandidate(JmsTemplate.class)
|
||||||
|
JmsMessagingTemplate jmsMessagingTemplate(JmsProperties properties, JmsTemplate jmsTemplate) {
|
||||||
|
JmsMessagingTemplate messagingTemplate = new JmsMessagingTemplate(jmsTemplate);
|
||||||
|
mapTemplateProperties(properties.getTemplate(), messagingTemplate);
|
||||||
|
return messagingTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mapTemplateProperties(Template properties, JmsMessagingTemplate messagingTemplate) {
|
||||||
|
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||||
|
map.from(properties::getDefaultDestination).to(messagingTemplate::setDefaultDestinationName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(JmsClient.class)
|
||||||
|
static class JmsClientConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(JmsClient.class)
|
||||||
|
@ConditionalOnSingleCandidate(JmsTemplate.class)
|
||||||
|
JmsClient jmsClient(JmsTemplate jmsTemplate) {
|
||||||
|
return JmsClient.create(jmsTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ import org.springframework.jms.config.JmsListenerContainerFactory;
|
||||||
import org.springframework.jms.config.JmsListenerEndpoint;
|
import org.springframework.jms.config.JmsListenerEndpoint;
|
||||||
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
|
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
|
||||||
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
|
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
|
||||||
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsMessagingTemplate;
|
||||||
import org.springframework.jms.core.JmsTemplate;
|
import org.springframework.jms.core.JmsTemplate;
|
||||||
import org.springframework.jms.listener.DefaultMessageListenerContainer;
|
import org.springframework.jms.listener.DefaultMessageListenerContainer;
|
||||||
|
@ -72,6 +73,7 @@ class JmsAutoConfigurationTests {
|
||||||
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(JmsAutoConfiguration.class))
|
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(JmsAutoConfiguration.class))
|
||||||
.run((context) -> assertThat(context).doesNotHaveBean(JmsTemplate.class)
|
.run((context) -> assertThat(context).doesNotHaveBean(JmsTemplate.class)
|
||||||
.doesNotHaveBean(JmsMessagingTemplate.class)
|
.doesNotHaveBean(JmsMessagingTemplate.class)
|
||||||
|
.doesNotHaveBean(JmsClient.class)
|
||||||
.doesNotHaveBean(DefaultJmsListenerContainerFactoryConfigurer.class)
|
.doesNotHaveBean(DefaultJmsListenerContainerFactoryConfigurer.class)
|
||||||
.doesNotHaveBean(DefaultJmsListenerContainerFactory.class));
|
.doesNotHaveBean(DefaultJmsListenerContainerFactory.class));
|
||||||
}
|
}
|
||||||
|
@ -80,10 +82,13 @@ class JmsAutoConfigurationTests {
|
||||||
void testDefaultJmsConfiguration() {
|
void testDefaultJmsConfiguration() {
|
||||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> {
|
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> {
|
||||||
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class);
|
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class);
|
||||||
|
assertThat(context).hasSingleBean(JmsTemplate.class)
|
||||||
|
.hasSingleBean(JmsMessagingTemplate.class)
|
||||||
|
.hasSingleBean(JmsClient.class);
|
||||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||||
JmsMessagingTemplate messagingTemplate = context.getBean(JmsMessagingTemplate.class);
|
|
||||||
assertThat(jmsTemplate.getConnectionFactory()).isEqualTo(connectionFactory);
|
assertThat(jmsTemplate.getConnectionFactory()).isEqualTo(connectionFactory);
|
||||||
assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate);
|
assertThat(context.getBean(JmsMessagingTemplate.class).getJmsTemplate()).isEqualTo(jmsTemplate);
|
||||||
|
assertThat(context.getBean(JmsClient.class)).hasFieldOrPropertyWithValue("jmsTemplate", jmsTemplate);
|
||||||
assertThat(context.containsBean("jmsListenerContainerFactory")).isTrue();
|
assertThat(context.containsBean("jmsListenerContainerFactory")).isTrue();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -101,6 +106,13 @@ class JmsAutoConfigurationTests {
|
||||||
.isEqualTo("fooBar"));
|
.isEqualTo("fooBar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testJmsClientBackOff() {
|
||||||
|
JmsClient userJmsClient = mock(JmsClient.class);
|
||||||
|
this.contextRunner.withBean("userJmsClient", JmsClient.class, () -> userJmsClient)
|
||||||
|
.run((context) -> assertThat(context.getBean(JmsClient.class)).isEqualTo(userJmsClient));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDefaultJmsListenerConfiguration() {
|
void testDefaultJmsListenerConfiguration() {
|
||||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((loaded) -> {
|
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((loaded) -> {
|
||||||
|
|
|
@ -20,14 +20,14 @@ import jakarta.jms.Queue;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class Producer implements CommandLineRunner {
|
public class Producer implements CommandLineRunner {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JmsMessagingTemplate jmsMessagingTemplate;
|
private JmsClient jmsClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Queue queue;
|
private Queue queue;
|
||||||
|
@ -39,7 +39,7 @@ public class Producer implements CommandLineRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(String msg) {
|
public void send(String msg) {
|
||||||
this.jmsMessagingTemplate.convertAndSend(this.queue, msg);
|
this.jmsClient.destination(this.queue).send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@ import jakarta.jms.Queue;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class Producer implements CommandLineRunner {
|
public class Producer implements CommandLineRunner {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JmsMessagingTemplate jmsMessagingTemplate;
|
private JmsClient jmsClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Queue queue;
|
private Queue queue;
|
||||||
|
@ -39,7 +39,7 @@ public class Producer implements CommandLineRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(String msg) {
|
public void send(String msg) {
|
||||||
this.jmsMessagingTemplate.convertAndSend(this.queue, msg);
|
this.jmsClient.destination(this.queue).send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@ import jakarta.jms.Queue;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
import org.springframework.jms.core.JmsClient;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class Producer implements CommandLineRunner {
|
public class Producer implements CommandLineRunner {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JmsMessagingTemplate jmsMessagingTemplate;
|
private JmsClient jmsClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Queue queue;
|
private Queue queue;
|
||||||
|
@ -39,7 +39,7 @@ public class Producer implements CommandLineRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(String msg) {
|
public void send(String msg) {
|
||||||
this.jmsMessagingTemplate.convertAndSend(this.queue, msg);
|
this.jmsClient.destination(this.queue).send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue