mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Add service connection for Testcontainers ActiveMQ
See gh-35080
This commit is contained in:
parent
ac2481f1a1
commit
63121dd08a
@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
|
|||||||
import org.springframework.boot.autoconfigure.jms.JmsProperties;
|
import org.springframework.boot.autoconfigure.jms.JmsProperties;
|
||||||
import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +36,7 @@ import org.springframework.context.annotation.Import;
|
|||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
|
* @author Eddú Meléndez
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration(before = JmsAutoConfiguration.class, after = JndiConnectionFactoryAutoConfiguration.class)
|
@AutoConfiguration(before = JmsAutoConfiguration.class, after = JndiConnectionFactoryAutoConfiguration.class)
|
||||||
@ -44,4 +46,38 @@ import org.springframework.context.annotation.Import;
|
|||||||
@Import({ ActiveMQXAConnectionFactoryConfiguration.class, ActiveMQConnectionFactoryConfiguration.class })
|
@Import({ ActiveMQXAConnectionFactoryConfiguration.class, ActiveMQConnectionFactoryConfiguration.class })
|
||||||
public class ActiveMQAutoConfiguration {
|
public class ActiveMQAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(ActiveMQConnectionDetails.class)
|
||||||
|
ActiveMQConnectionDetails activemqConnectionDetails(ActiveMQProperties properties) {
|
||||||
|
return new PropertiesActiveMQConnectionDetails(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts {@link ActiveMQProperties} to {@link ActiveMQConnectionDetails}.
|
||||||
|
*/
|
||||||
|
static class PropertiesActiveMQConnectionDetails implements ActiveMQConnectionDetails {
|
||||||
|
|
||||||
|
private final ActiveMQProperties properties;
|
||||||
|
|
||||||
|
PropertiesActiveMQConnectionDetails(ActiveMQProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBrokerUrl() {
|
||||||
|
return this.properties.determineBrokerUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUser() {
|
||||||
|
return this.properties.getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.properties.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.activemq;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details required to establish a connection to an ActiveMQ service.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
public interface ActiveMQConnectionDetails extends ConnectionDetails {
|
||||||
|
|
||||||
|
String getBrokerUrl();
|
||||||
|
|
||||||
|
String getUser();
|
||||||
|
|
||||||
|
String getPassword();
|
||||||
|
|
||||||
|
}
|
@ -39,6 +39,7 @@ import org.springframework.jms.connection.CachingConnectionFactory;
|
|||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Aurélien Leboulanger
|
* @author Aurélien Leboulanger
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ConditionalOnMissingBean(ConnectionFactory.class)
|
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||||
@ -52,13 +53,16 @@ class ActiveMQConnectionFactoryConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false")
|
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false")
|
||||||
ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
|
ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
|
||||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
|
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers,
|
||||||
return createJmsConnectionFactory(properties, factoryCustomizers);
|
ActiveMQConnectionDetails connectionDetails) {
|
||||||
|
return createJmsConnectionFactory(properties, factoryCustomizers, connectionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveMQConnectionFactory createJmsConnectionFactory(ActiveMQProperties properties,
|
private static ActiveMQConnectionFactory createJmsConnectionFactory(ActiveMQProperties properties,
|
||||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
|
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers,
|
||||||
return new ActiveMQConnectionFactoryFactory(properties, factoryCustomizers.orderedStream().toList())
|
ActiveMQConnectionDetails connectionDetails) {
|
||||||
|
return new ActiveMQConnectionFactoryFactory(properties, factoryCustomizers.orderedStream().toList(),
|
||||||
|
connectionDetails)
|
||||||
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +74,11 @@ class ActiveMQConnectionFactoryConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
CachingConnectionFactory jmsConnectionFactory(JmsProperties jmsProperties, ActiveMQProperties properties,
|
CachingConnectionFactory jmsConnectionFactory(JmsProperties jmsProperties, ActiveMQProperties properties,
|
||||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
|
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers,
|
||||||
|
ActiveMQConnectionDetails connectionDetails) {
|
||||||
JmsProperties.Cache cacheProperties = jmsProperties.getCache();
|
JmsProperties.Cache cacheProperties = jmsProperties.getCache();
|
||||||
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(
|
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(
|
||||||
createJmsConnectionFactory(properties, factoryCustomizers));
|
createJmsConnectionFactory(properties, factoryCustomizers, connectionDetails));
|
||||||
connectionFactory.setCacheConsumers(cacheProperties.isConsumers());
|
connectionFactory.setCacheConsumers(cacheProperties.isConsumers());
|
||||||
connectionFactory.setCacheProducers(cacheProperties.isProducers());
|
connectionFactory.setCacheProducers(cacheProperties.isProducers());
|
||||||
connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize());
|
connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize());
|
||||||
@ -91,9 +96,10 @@ class ActiveMQConnectionFactoryConfiguration {
|
|||||||
@Bean(destroyMethod = "stop")
|
@Bean(destroyMethod = "stop")
|
||||||
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true")
|
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true")
|
||||||
JmsPoolConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
|
JmsPoolConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
|
||||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
|
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers,
|
||||||
|
ActiveMQConnectionDetails connectionDetails) {
|
||||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(properties,
|
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(properties,
|
||||||
factoryCustomizers.orderedStream().toList())
|
factoryCustomizers.orderedStream().toList(), connectionDetails)
|
||||||
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
||||||
return new JmsPoolConnectionFactoryFactory(properties.getPool())
|
return new JmsPoolConnectionFactoryFactory(properties.getPool())
|
||||||
.createPooledConnectionFactory(connectionFactory);
|
.createPooledConnectionFactory(connectionFactory);
|
||||||
|
@ -32,20 +32,22 @@ import org.springframework.util.StringUtils;
|
|||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
class ActiveMQConnectionFactoryFactory {
|
class ActiveMQConnectionFactoryFactory {
|
||||||
|
|
||||||
private static final String DEFAULT_NETWORK_BROKER_URL = "tcp://localhost:61616";
|
|
||||||
|
|
||||||
private final ActiveMQProperties properties;
|
private final ActiveMQProperties properties;
|
||||||
|
|
||||||
private final List<ActiveMQConnectionFactoryCustomizer> factoryCustomizers;
|
private final List<ActiveMQConnectionFactoryCustomizer> factoryCustomizers;
|
||||||
|
|
||||||
|
private final ActiveMQConnectionDetails connectionDetails;
|
||||||
|
|
||||||
ActiveMQConnectionFactoryFactory(ActiveMQProperties properties,
|
ActiveMQConnectionFactoryFactory(ActiveMQProperties properties,
|
||||||
List<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
|
List<ActiveMQConnectionFactoryCustomizer> factoryCustomizers, ActiveMQConnectionDetails connectionDetails) {
|
||||||
Assert.notNull(properties, "Properties must not be null");
|
Assert.notNull(properties, "Properties must not be null");
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.factoryCustomizers = (factoryCustomizers != null) ? factoryCustomizers : Collections.emptyList();
|
this.factoryCustomizers = (factoryCustomizers != null) ? factoryCustomizers : Collections.emptyList();
|
||||||
|
this.connectionDetails = connectionDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
<T extends ActiveMQConnectionFactory> T createConnectionFactory(Class<T> factoryClass) {
|
<T extends ActiveMQConnectionFactory> T createConnectionFactory(Class<T> factoryClass) {
|
||||||
@ -79,9 +81,9 @@ class ActiveMQConnectionFactoryFactory {
|
|||||||
|
|
||||||
private <T extends ActiveMQConnectionFactory> T createConnectionFactoryInstance(Class<T> factoryClass)
|
private <T extends ActiveMQConnectionFactory> T createConnectionFactoryInstance(Class<T> factoryClass)
|
||||||
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||||
String brokerUrl = determineBrokerUrl();
|
String brokerUrl = this.connectionDetails.getBrokerUrl();
|
||||||
String user = this.properties.getUser();
|
String user = this.connectionDetails.getUser();
|
||||||
String password = this.properties.getPassword();
|
String password = this.connectionDetails.getPassword();
|
||||||
if (StringUtils.hasLength(user) && StringUtils.hasLength(password)) {
|
if (StringUtils.hasLength(user) && StringUtils.hasLength(password)) {
|
||||||
return factoryClass.getConstructor(String.class, String.class, String.class)
|
return factoryClass.getConstructor(String.class, String.class, String.class)
|
||||||
.newInstance(user, password, brokerUrl);
|
.newInstance(user, password, brokerUrl);
|
||||||
@ -95,11 +97,4 @@ class ActiveMQConnectionFactoryFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String determineBrokerUrl() {
|
|
||||||
if (this.properties.getBrokerUrl() != null) {
|
|
||||||
return this.properties.getBrokerUrl();
|
|
||||||
}
|
|
||||||
return DEFAULT_NETWORK_BROKER_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,14 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
|||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Aurélien Leboulanger
|
* @author Aurélien Leboulanger
|
||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
|
* @author Eddú Meléndez
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = "spring.activemq")
|
@ConfigurationProperties(prefix = "spring.activemq")
|
||||||
public class ActiveMQProperties {
|
public class ActiveMQProperties {
|
||||||
|
|
||||||
|
private static final String DEFAULT_NETWORK_BROKER_URL = "tcp://localhost:61616";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL of the ActiveMQ broker. Auto-generated by default.
|
* URL of the ActiveMQ broker. Auto-generated by default.
|
||||||
*/
|
*/
|
||||||
@ -128,6 +131,13 @@ public class ActiveMQProperties {
|
|||||||
return this.packages;
|
return this.packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String determineBrokerUrl() {
|
||||||
|
if (this.brokerUrl != null) {
|
||||||
|
return this.brokerUrl;
|
||||||
|
}
|
||||||
|
return DEFAULT_NETWORK_BROKER_URL;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Packages {
|
public static class Packages {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +36,7 @@ import org.springframework.context.annotation.Primary;
|
|||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Aurélien Leboulanger
|
* @author Aurélien Leboulanger
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ConditionalOnClass(TransactionManager.class)
|
@ConditionalOnClass(TransactionManager.class)
|
||||||
@ -46,10 +47,10 @@ class ActiveMQXAConnectionFactoryConfiguration {
|
|||||||
@Primary
|
@Primary
|
||||||
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
|
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
|
||||||
ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
|
ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
|
||||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers, XAConnectionFactoryWrapper wrapper)
|
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers, XAConnectionFactoryWrapper wrapper,
|
||||||
throws Exception {
|
ActiveMQConnectionDetails connectionDetails) throws Exception {
|
||||||
ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(properties,
|
ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(properties,
|
||||||
factoryCustomizers.orderedStream().toList())
|
factoryCustomizers.orderedStream().toList(), connectionDetails)
|
||||||
.createConnectionFactory(ActiveMQXAConnectionFactory.class);
|
.createConnectionFactory(ActiveMQXAConnectionFactory.class);
|
||||||
return wrapper.wrapConnectionFactory(connectionFactory);
|
return wrapper.wrapConnectionFactory(connectionFactory);
|
||||||
}
|
}
|
||||||
@ -58,8 +59,10 @@ class ActiveMQXAConnectionFactoryConfiguration {
|
|||||||
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false",
|
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false",
|
||||||
matchIfMissing = true)
|
matchIfMissing = true)
|
||||||
ActiveMQConnectionFactory nonXaJmsConnectionFactory(ActiveMQProperties properties,
|
ActiveMQConnectionFactory nonXaJmsConnectionFactory(ActiveMQProperties properties,
|
||||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
|
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers,
|
||||||
return new ActiveMQConnectionFactoryFactory(properties, factoryCustomizers.orderedStream().toList())
|
ActiveMQConnectionDetails connectionDetails) {
|
||||||
|
return new ActiveMQConnectionFactoryFactory(properties, factoryCustomizers.orderedStream().toList(),
|
||||||
|
connectionDetails)
|
||||||
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ import static org.mockito.Mockito.mockingDetails;
|
|||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Aurélien Leboulanger
|
* @author Aurélien Leboulanger
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
class ActiveMQAutoConfigurationTests {
|
class ActiveMQAutoConfigurationTests {
|
||||||
|
|
||||||
@ -233,6 +234,27 @@ class ActiveMQAutoConfigurationTests {
|
|||||||
.doesNotHaveBean("jmsConnectionFactory"));
|
.doesNotHaveBean("jmsConnectionFactory"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||||
|
this.contextRunner.run((context) -> assertThat(context)
|
||||||
|
.hasSingleBean(ActiveMQAutoConfiguration.PropertiesActiveMQConnectionDetails.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConnectionFactoryWithOverridesWhenUsingCustomConnectionDetails() {
|
||||||
|
this.contextRunner.withClassLoader(new FilteredClassLoader(CachingConnectionFactory.class))
|
||||||
|
.withPropertyValues("spring.activemq.pool.enabled=false", "spring.jms.cache.enabled=false")
|
||||||
|
.withUserConfiguration(TestConnectionDetailsConfiguration.class)
|
||||||
|
.run((context) -> {
|
||||||
|
assertThat(context).hasSingleBean(ActiveMQConnectionDetails.class)
|
||||||
|
.doesNotHaveBean(ActiveMQAutoConfiguration.PropertiesActiveMQConnectionDetails.class);
|
||||||
|
ActiveMQConnectionFactory connectionFactory = context.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertThat(connectionFactory.getBrokerURL()).isEqualTo("tcp://localhost:12345");
|
||||||
|
assertThat(connectionFactory.getUserName()).isEqualTo("springuser");
|
||||||
|
assertThat(connectionFactory.getPassword()).isEqualTo("spring");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class EmptyConfiguration {
|
static class EmptyConfiguration {
|
||||||
|
|
||||||
@ -261,4 +283,29 @@ class ActiveMQAutoConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class TestConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ActiveMQConnectionDetails activemqConnectionDetails() {
|
||||||
|
return new ActiveMQConnectionDetails() {
|
||||||
|
@Override
|
||||||
|
public String getBrokerUrl() {
|
||||||
|
return "tcp://localhost:12345";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUser() {
|
||||||
|
return "springuser";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return "spring";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Aurélien Leboulanger
|
* @author Aurélien Leboulanger
|
||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
class ActiveMQPropertiesTests {
|
class ActiveMQPropertiesTests {
|
||||||
|
|
||||||
@ -38,13 +39,13 @@ class ActiveMQPropertiesTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getBrokerUrlIsLocalhostByDefault() {
|
void getBrokerUrlIsLocalhostByDefault() {
|
||||||
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo(DEFAULT_NETWORK_BROKER_URL);
|
assertThat(this.properties.determineBrokerUrl()).isEqualTo(DEFAULT_NETWORK_BROKER_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getBrokerUrlUseExplicitBrokerUrl() {
|
void getBrokerUrlUseExplicitBrokerUrl() {
|
||||||
this.properties.setBrokerUrl("tcp://activemq.example.com:71717");
|
this.properties.setBrokerUrl("tcp://activemq.example.com:71717");
|
||||||
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo("tcp://activemq.example.com:71717");
|
assertThat(this.properties.determineBrokerUrl()).isEqualTo("tcp://activemq.example.com:71717");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -66,7 +67,8 @@ class ActiveMQPropertiesTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ActiveMQConnectionFactoryFactory createFactory(ActiveMQProperties properties) {
|
private ActiveMQConnectionFactoryFactory createFactory(ActiveMQProperties properties) {
|
||||||
return new ActiveMQConnectionFactoryFactory(properties, Collections.emptyList());
|
return new ActiveMQConnectionFactoryFactory(properties, Collections.emptyList(),
|
||||||
|
new ActiveMQAutoConfiguration.PropertiesActiveMQConnectionDetails(properties));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -946,6 +946,9 @@ The following service connection factories are provided in the `spring-boot-test
|
|||||||
|===
|
|===
|
||||||
| Connection Details | Matched on
|
| Connection Details | Matched on
|
||||||
|
|
||||||
|
| `ActiveMQConnectionDetails`
|
||||||
|
| Containers named "symptoma/activemq"
|
||||||
|
|
||||||
| `CassandraConnectionDetails`
|
| `CassandraConnectionDetails`
|
||||||
| Containers of type `CassandraContainer`
|
| Containers of type `CassandraContainer`
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ dependencies {
|
|||||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||||
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||||
testImplementation("ch.qos.logback:logback-classic")
|
testImplementation("ch.qos.logback:logback-classic")
|
||||||
|
testImplementation("org.apache.activemq:activemq-client-jakarta")
|
||||||
testImplementation("org.assertj:assertj-core")
|
testImplementation("org.assertj:assertj-core")
|
||||||
testImplementation("org.awaitility:awaitility")
|
testImplementation("org.awaitility:awaitility")
|
||||||
testImplementation("org.influxdb:influxdb-java")
|
testImplementation("org.influxdb:influxdb-java")
|
||||||
@ -45,6 +46,7 @@ dependencies {
|
|||||||
testImplementation("org.mockito:mockito-core")
|
testImplementation("org.mockito:mockito-core")
|
||||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||||
testImplementation("org.springframework:spring-core-test")
|
testImplementation("org.springframework:spring-core-test")
|
||||||
|
testImplementation("org.springframework:spring-jms")
|
||||||
testImplementation("org.springframework:spring-r2dbc")
|
testImplementation("org.springframework:spring-r2dbc")
|
||||||
testImplementation("org.springframework.amqp:spring-rabbit")
|
testImplementation("org.springframework.amqp:spring-rabbit")
|
||||||
testImplementation("org.springframework.kafka:spring-kafka")
|
testImplementation("org.springframework.kafka:spring-kafka")
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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.testcontainers.service.connection.activemq;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.testcontainers.containers.Container;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails;
|
||||||
|
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
|
||||||
|
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
|
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ContainerConnectionDetailsFactory} to create {@link ActiveMQConnectionDetails}
|
||||||
|
* from a {@link ServiceConnection @ServiceConnection}-annotated {@link GenericContainer}
|
||||||
|
* using the {@code "symptoma/activemq"} image.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
*/
|
||||||
|
class ActiveMQContainerConnectionDetailsFactory
|
||||||
|
extends ContainerConnectionDetailsFactory<ActiveMQConnectionDetails, Container<?>> {
|
||||||
|
|
||||||
|
ActiveMQContainerConnectionDetailsFactory() {
|
||||||
|
super("symptoma/activemq");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ActiveMQConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) {
|
||||||
|
return new ActiveMQContainerConnectionDetails(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ActiveMQContainerConnectionDetails extends ContainerConnectionDetails
|
||||||
|
implements ActiveMQConnectionDetails {
|
||||||
|
|
||||||
|
private final String brokerUrl;
|
||||||
|
|
||||||
|
private final Map<String, String> envVars;
|
||||||
|
|
||||||
|
private ActiveMQContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) {
|
||||||
|
super(source);
|
||||||
|
this.brokerUrl = "tcp://" + source.getContainer().getHost() + ":"
|
||||||
|
+ source.getContainer().getFirstMappedPort();
|
||||||
|
this.envVars = source.getContainer().getEnvMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBrokerUrl() {
|
||||||
|
return this.brokerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUser() {
|
||||||
|
return this.envVars.get("ACTIVEMQ_USERNAME");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.envVars.get("ACTIVEMQ_PASSWORD");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for testcontainers ActiveMQ service connections.
|
||||||
|
*/
|
||||||
|
package org.springframework.boot.testcontainers.service.connection.activemq;
|
@ -8,6 +8,7 @@ org.springframework.boot.testcontainers.service.connection.ServiceConnectionCont
|
|||||||
|
|
||||||
# Connection Details Factories
|
# Connection Details Factories
|
||||||
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
|
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
|
||||||
|
org.springframework.boot.testcontainers.service.connection.activemq.ActiveMQContainerConnectionDetailsFactory,\
|
||||||
org.springframework.boot.testcontainers.service.connection.amqp.RabbitContainerConnectionDetailsFactory,\
|
org.springframework.boot.testcontainers.service.connection.amqp.RabbitContainerConnectionDetailsFactory,\
|
||||||
org.springframework.boot.testcontainers.service.connection.cassandra.CassandraContainerConnectionDetailsFactory,\
|
org.springframework.boot.testcontainers.service.connection.cassandra.CassandraContainerConnectionDetailsFactory,\
|
||||||
org.springframework.boot.testcontainers.service.connection.couchbase.CouchbaseContainerConnectionDetailsFactory,\
|
org.springframework.boot.testcontainers.service.connection.couchbase.CouchbaseContainerConnectionDetailsFactory,\
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.testcontainers.service.connection.activemq;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
|
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||||
|
import org.springframework.boot.testsupport.testcontainers.ActiveMQContainer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.jms.annotation.JmsListener;
|
||||||
|
import org.springframework.jms.core.JmsMessagingTemplate;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ActiveMQContainerConnectionDetailsFactory}.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
*/
|
||||||
|
@SpringJUnitConfig
|
||||||
|
@Testcontainers(disabledWithoutDocker = true)
|
||||||
|
class ActiveMQContainerConnectionDetailsFactoryIntegrationTests {
|
||||||
|
|
||||||
|
@Container
|
||||||
|
@ServiceConnection
|
||||||
|
static final ActiveMQContainer activemq = new ActiveMQContainer();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JmsMessagingTemplate jmsTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TestListener listener;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void connectionCanBeMadeToActiveMQContainer() {
|
||||||
|
this.jmsTemplate.convertAndSend("sample.queue", "message");
|
||||||
|
Awaitility.waitAtMost(Duration.ofMinutes(1))
|
||||||
|
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ImportAutoConfiguration({ ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class })
|
||||||
|
static class TestConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
TestListener testListener() {
|
||||||
|
return new TestListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestListener {
|
||||||
|
|
||||||
|
private final List<String> messages = new ArrayList<>();
|
||||||
|
|
||||||
|
@JmsListener(destination = "sample.queue")
|
||||||
|
void processMessage(String message) {
|
||||||
|
this.messages.add(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,8 @@ description = "Spring Boot Actuator ActiveMQ smoke test"
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-activemq"))
|
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-activemq"))
|
||||||
|
|
||||||
|
testImplementation("org.awaitility:awaitility")
|
||||||
|
testImplementation("org.testcontainers:testcontainers")
|
||||||
testImplementation("org.testcontainers:junit-jupiter")
|
testImplementation("org.testcontainers:junit-jupiter")
|
||||||
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
|
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
|
||||||
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
|
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package smoketest.activemq;
|
package smoketest.activemq;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
@ -25,9 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.system.CapturedOutput;
|
import org.springframework.boot.test.system.CapturedOutput;
|
||||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||||
import org.springframework.boot.testsupport.testcontainers.ActiveMQContainer;
|
import org.springframework.boot.testsupport.testcontainers.ActiveMQContainer;
|
||||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
|
||||||
import org.springframework.test.context.DynamicPropertySource;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ -43,21 +45,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
class SampleActiveMqTests {
|
class SampleActiveMqTests {
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
|
@ServiceConnection
|
||||||
private static final ActiveMQContainer container = new ActiveMQContainer();
|
private static final ActiveMQContainer container = new ActiveMQContainer();
|
||||||
|
|
||||||
@DynamicPropertySource
|
|
||||||
static void activeMqProperties(DynamicPropertyRegistry registry) {
|
|
||||||
registry.add("spring.activemq.broker-url", container::getBrokerUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Producer producer;
|
private Producer producer;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sendSimpleMessage(CapturedOutput output) throws InterruptedException {
|
void sendSimpleMessage(CapturedOutput output) {
|
||||||
this.producer.send("Test message");
|
this.producer.send("Test message");
|
||||||
Thread.sleep(1000L);
|
Awaitility.waitAtMost(Duration.ofMinutes(1)).untilAsserted(() -> assertThat(output).contains("Test message"));
|
||||||
assertThat(output).contains("Test message");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user