Add service connection for Docker Compose and Testcontainers Artemis

See gh-39311
This commit is contained in:
Eddú Meléndez
2024-01-25 17:07:08 -05:00
committed by Moritz Halbritter
parent ee17c4322b
commit f15cd93a35
18 changed files with 589 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2024 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.
@@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.JmsProperties;
import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
/**
@@ -48,4 +49,43 @@ import org.springframework.context.annotation.Import;
ArtemisConnectionFactoryConfiguration.class })
public class ArtemisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ArtemisConnectionDetails.class)
ArtemisConnectionDetails artemisConnectionDetails(ArtemisProperties properties) {
return new PropertiesArtemisConnectionDetails(properties);
}
/**
* Adapts {@link ArtemisProperties} to {@link ArtemisConnectionDetails}.
*/
static class PropertiesArtemisConnectionDetails implements ArtemisConnectionDetails {
private final ArtemisProperties properties;
PropertiesArtemisConnectionDetails(ArtemisProperties properties) {
this.properties = properties;
}
@Override
public ArtemisMode getMode() {
return this.properties.getMode();
}
@Override
public String getBrokerUrl() {
return this.properties.getBrokerUrl();
}
@Override
public String getUser() {
return this.properties.getUser();
}
@Override
public String getPassword() {
return this.properties.getPassword();
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2012-2024 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.artemis;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
/**
* Details required to establish a connection to an Artemis service.
*
* @author Eddú Meléndez
* @since 3.3.0
*/
public interface ArtemisConnectionDetails extends ConnectionDetails {
ArtemisMode getMode();
String getBrokerUrl();
String getUser();
String getPassword();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -49,13 +49,14 @@ class ArtemisConnectionFactoryConfiguration {
@Bean(name = "jmsConnectionFactory")
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false")
ActiveMQConnectionFactory jmsConnectionFactory(ArtemisProperties properties, ListableBeanFactory beanFactory) {
return createJmsConnectionFactory(properties, beanFactory);
ActiveMQConnectionFactory jmsConnectionFactory(ArtemisProperties properties, ListableBeanFactory beanFactory,
ArtemisConnectionDetails connectionDetails) {
return createJmsConnectionFactory(properties, connectionDetails, beanFactory);
}
private static ActiveMQConnectionFactory createJmsConnectionFactory(ArtemisProperties properties,
ListableBeanFactory beanFactory) {
return new ArtemisConnectionFactoryFactory(beanFactory, properties)
ArtemisConnectionDetails connectionDetails, ListableBeanFactory beanFactory) {
return new ArtemisConnectionFactoryFactory(beanFactory, properties, connectionDetails)
.createConnectionFactory(ActiveMQConnectionFactory.class);
}
@@ -67,10 +68,11 @@ class ArtemisConnectionFactoryConfiguration {
@Bean(name = "jmsConnectionFactory")
CachingConnectionFactory cachingJmsConnectionFactory(JmsProperties jmsProperties,
ArtemisProperties properties, ListableBeanFactory beanFactory) {
ArtemisProperties properties, ArtemisConnectionDetails connectionDetails,
ListableBeanFactory beanFactory) {
JmsProperties.Cache cacheProperties = jmsProperties.getCache();
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(
createJmsConnectionFactory(properties, beanFactory));
createJmsConnectionFactory(properties, connectionDetails, beanFactory));
connectionFactory.setCacheConsumers(cacheProperties.isConsumers());
connectionFactory.setCacheProducers(cacheProperties.isProducers());
connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize());
@@ -87,8 +89,10 @@ class ArtemisConnectionFactoryConfiguration {
static class PooledConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop")
JmsPoolConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, ArtemisProperties properties) {
ActiveMQConnectionFactory connectionFactory = new ArtemisConnectionFactoryFactory(beanFactory, properties)
JmsPoolConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, ArtemisProperties properties,
ArtemisConnectionDetails connectionDetails) {
ActiveMQConnectionFactory connectionFactory = new ArtemisConnectionFactoryFactory(beanFactory, properties,
connectionDetails)
.createConnectionFactory(ActiveMQConnectionFactory.class);
return new JmsPoolConnectionFactoryFactory(properties.getPool())
.createPooledConnectionFactory(connectionFactory);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2024 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.
@@ -47,13 +47,18 @@ class ArtemisConnectionFactoryFactory {
private final ArtemisProperties properties;
private final ArtemisConnectionDetails connectionDetails;
private final ListableBeanFactory beanFactory;
ArtemisConnectionFactoryFactory(ListableBeanFactory beanFactory, ArtemisProperties properties) {
ArtemisConnectionFactoryFactory(ListableBeanFactory beanFactory, ArtemisProperties properties,
ArtemisConnectionDetails connectionDetails) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.notNull(properties, "Properties must not be null");
Assert.notNull(connectionDetails, "ConnectionDetails must not be null");
this.beanFactory = beanFactory;
this.properties = properties;
this.connectionDetails = connectionDetails;
}
<T extends ActiveMQConnectionFactory> T createConnectionFactory(Class<T> factoryClass) {
@@ -80,7 +85,7 @@ class ArtemisConnectionFactoryFactory {
}
private <T extends ActiveMQConnectionFactory> T doCreateConnectionFactory(Class<T> factoryClass) throws Exception {
ArtemisMode mode = this.properties.getMode();
ArtemisMode mode = this.connectionDetails.getMode();
if (mode == null) {
mode = deduceMode();
}
@@ -127,17 +132,17 @@ class ArtemisConnectionFactoryFactory {
private <T extends ActiveMQConnectionFactory> T createNativeConnectionFactory(Class<T> factoryClass)
throws Exception {
T connectionFactory = newNativeConnectionFactory(factoryClass);
String user = this.properties.getUser();
String user = this.connectionDetails.getUser();
if (StringUtils.hasText(user)) {
connectionFactory.setUser(user);
connectionFactory.setPassword(this.properties.getPassword());
connectionFactory.setPassword(this.connectionDetails.getPassword());
}
return connectionFactory;
}
private <T extends ActiveMQConnectionFactory> T newNativeConnectionFactory(Class<T> factoryClass) throws Exception {
String brokerUrl = StringUtils.hasText(this.properties.getBrokerUrl()) ? this.properties.getBrokerUrl()
: DEFAULT_BROKER_URL;
String brokerUrl = StringUtils.hasText(this.connectionDetails.getBrokerUrl())
? this.connectionDetails.getBrokerUrl() : DEFAULT_BROKER_URL;
Constructor<T> constructor = factoryClass.getConstructor(String.class);
return constructor.newInstance(brokerUrl);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -44,15 +44,16 @@ class ArtemisXAConnectionFactoryConfiguration {
@Primary
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, ArtemisProperties properties,
XAConnectionFactoryWrapper wrapper) throws Exception {
return wrapper.wrapConnectionFactory(new ArtemisConnectionFactoryFactory(beanFactory, properties)
.createConnectionFactory(ActiveMQXAConnectionFactory.class));
ArtemisConnectionDetails connectionDetails, XAConnectionFactoryWrapper wrapper) throws Exception {
return wrapper
.wrapConnectionFactory(new ArtemisConnectionFactoryFactory(beanFactory, properties, connectionDetails)
.createConnectionFactory(ActiveMQXAConnectionFactory.class));
}
@Bean
ActiveMQXAConnectionFactory nonXaJmsConnectionFactory(ListableBeanFactory beanFactory,
ArtemisProperties properties) {
return new ArtemisConnectionFactoryFactory(beanFactory, properties)
ActiveMQXAConnectionFactory nonXaJmsConnectionFactory(ListableBeanFactory beanFactory, ArtemisProperties properties,
ArtemisConnectionDetails connectionDetails) {
return new ArtemisConnectionFactoryFactory(beanFactory, properties, connectionDetails)
.createConnectionFactory(ActiveMQXAConnectionFactory.class);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -46,6 +46,7 @@ import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration.PropertiesArtemisConnectionDetails;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -371,6 +372,27 @@ class ArtemisAutoConfigurationTests {
.run((context) -> assertThat(context).doesNotHaveBean(ActiveMQConnectionFactory.class));
}
@Test
void definesPropertiesBasedConnectionDetailsByDefault() {
this.contextRunner
.run((context) -> assertThat(context).hasSingleBean(PropertiesArtemisConnectionDetails.class));
}
@Test
void testConnectionFactoryWithOverridesWhenUsingCustomConnectionDetails() {
this.contextRunner.withClassLoader(new FilteredClassLoader(CachingConnectionFactory.class))
.withPropertyValues("spring.artemis.pool.enabled=false", "spring.jms.cache.enabled=false")
.withUserConfiguration(TestConnectionDetailsConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(ArtemisConnectionDetails.class)
.doesNotHaveBean(PropertiesArtemisConnectionDetails.class);
ActiveMQConnectionFactory connectionFactory = context.getBean(ActiveMQConnectionFactory.class);
assertThat(connectionFactory.toURI().toString()).startsWith("tcp://localhost:12345");
assertThat(connectionFactory.getUser()).isEqualTo("springuser");
assertThat(connectionFactory.getPassword()).isEqualTo("spring");
});
}
private ConnectionFactory getConnectionFactory(AssertableApplicationContext context) {
assertThat(context).hasSingleBean(ConnectionFactory.class).hasBean("jmsConnectionFactory");
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class);
@@ -496,4 +518,36 @@ class ArtemisAutoConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
static class TestConnectionDetailsConfiguration {
@Bean
ArtemisConnectionDetails activemqConnectionDetails() {
return new ArtemisConnectionDetails() {
@Override
public ArtemisMode getMode() {
return ArtemisMode.NATIVE;
}
@Override
public String getBrokerUrl() {
return "tcp://localhost:12345";
}
@Override
public String getUser() {
return "springuser";
}
@Override
public String getPassword() {
return "spring";
}
};
}
}
}