Browse Source
* pr/35048: Polish "Reintroduce support for ActiveMQ" Reintroduce support for ActiveMQ Closes gh-35048pull/35090/head
25 changed files with 1237 additions and 5 deletions
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* 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 jakarta.jms.ConnectionFactory; |
||||
import org.apache.activemq.ActiveMQConnectionFactory; |
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
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.Import; |
||||
|
||||
/** |
||||
* {@link EnableAutoConfiguration Auto-configuration} to integrate with an ActiveMQ |
||||
* broker. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @author Phillip Webb |
||||
* @since 3.1.0 |
||||
*/ |
||||
@AutoConfiguration(before = JmsAutoConfiguration.class, after = JndiConnectionFactoryAutoConfiguration.class) |
||||
@ConditionalOnClass({ ConnectionFactory.class, ActiveMQConnectionFactory.class }) |
||||
@ConditionalOnMissingBean(ConnectionFactory.class) |
||||
@EnableConfigurationProperties({ ActiveMQProperties.class, JmsProperties.class }) |
||||
@Import({ ActiveMQXAConnectionFactoryConfiguration.class, ActiveMQConnectionFactoryConfiguration.class }) |
||||
public class ActiveMQAutoConfiguration { |
||||
|
||||
} |
||||
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
/* |
||||
* 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 java.util.stream.Collectors; |
||||
|
||||
import jakarta.jms.ConnectionFactory; |
||||
import org.apache.activemq.ActiveMQConnectionFactory; |
||||
import org.apache.commons.pool2.PooledObject; |
||||
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory; |
||||
|
||||
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.ConditionalOnProperty; |
||||
import org.springframework.boot.autoconfigure.jms.JmsPoolConnectionFactoryFactory; |
||||
import org.springframework.boot.autoconfigure.jms.JmsProperties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.jms.connection.CachingConnectionFactory; |
||||
|
||||
/** |
||||
* Configuration for ActiveMQ {@link ConnectionFactory}. |
||||
* |
||||
* @author Greg Turnquist |
||||
* @author Stephane Nicoll |
||||
* @author Phillip Webb |
||||
* @author Andy Wilkinson |
||||
* @author Aurélien Leboulanger |
||||
*/ |
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnMissingBean(ConnectionFactory.class) |
||||
class ActiveMQConnectionFactoryConfiguration { |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", |
||||
matchIfMissing = true) |
||||
static class SimpleConnectionFactoryConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false") |
||||
ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties, |
||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { |
||||
return createJmsConnectionFactory(properties, factoryCustomizers); |
||||
} |
||||
|
||||
private static ActiveMQConnectionFactory createJmsConnectionFactory(ActiveMQProperties properties, |
||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { |
||||
return new ActiveMQConnectionFactoryFactory(properties, |
||||
factoryCustomizers.orderedStream().collect(Collectors.toList())) |
||||
.createConnectionFactory(ActiveMQConnectionFactory.class); |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnClass(CachingConnectionFactory.class) |
||||
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "true", |
||||
matchIfMissing = true) |
||||
static class CachingConnectionFactoryConfiguration { |
||||
|
||||
@Bean |
||||
CachingConnectionFactory jmsConnectionFactory(JmsProperties jmsProperties, ActiveMQProperties properties, |
||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { |
||||
JmsProperties.Cache cacheProperties = jmsProperties.getCache(); |
||||
CachingConnectionFactory connectionFactory = new CachingConnectionFactory( |
||||
createJmsConnectionFactory(properties, factoryCustomizers)); |
||||
connectionFactory.setCacheConsumers(cacheProperties.isConsumers()); |
||||
connectionFactory.setCacheProducers(cacheProperties.isProducers()); |
||||
connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize()); |
||||
return connectionFactory; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class }) |
||||
static class PooledConnectionFactoryConfiguration { |
||||
|
||||
@Bean(destroyMethod = "stop") |
||||
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true") |
||||
JmsPoolConnectionFactory jmsConnectionFactory(ActiveMQProperties properties, |
||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { |
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(properties, |
||||
factoryCustomizers.orderedStream().collect(Collectors.toList())) |
||||
.createConnectionFactory(ActiveMQConnectionFactory.class); |
||||
return new JmsPoolConnectionFactoryFactory(properties.getPool()) |
||||
.createPooledConnectionFactory(connectionFactory); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* 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.apache.activemq.ActiveMQConnectionFactory; |
||||
|
||||
/** |
||||
* Callback interface that can be implemented by beans wishing to customize the |
||||
* {@link ActiveMQConnectionFactory} whilst retaining default auto-configuration. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 3.1.0 |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface ActiveMQConnectionFactoryCustomizer { |
||||
|
||||
/** |
||||
* Customize the {@link ActiveMQConnectionFactory}. |
||||
* @param factory the factory to customize |
||||
*/ |
||||
void customize(ActiveMQConnectionFactory factory); |
||||
|
||||
} |
||||
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
/* |
||||
* 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 java.lang.reflect.InvocationTargetException; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory; |
||||
|
||||
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQProperties.Packages; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Factory to create a {@link ActiveMQConnectionFactory} instance from properties defined |
||||
* in {@link ActiveMQProperties}. |
||||
* |
||||
* @author Phillip Webb |
||||
* @author Venil Noronha |
||||
*/ |
||||
class ActiveMQConnectionFactoryFactory { |
||||
|
||||
private static final String DEFAULT_NETWORK_BROKER_URL = "tcp://localhost:61616"; |
||||
|
||||
private final ActiveMQProperties properties; |
||||
|
||||
private final List<ActiveMQConnectionFactoryCustomizer> factoryCustomizers; |
||||
|
||||
ActiveMQConnectionFactoryFactory(ActiveMQProperties properties, |
||||
List<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { |
||||
Assert.notNull(properties, "Properties must not be null"); |
||||
this.properties = properties; |
||||
this.factoryCustomizers = (factoryCustomizers != null) ? factoryCustomizers : Collections.emptyList(); |
||||
} |
||||
|
||||
<T extends ActiveMQConnectionFactory> T createConnectionFactory(Class<T> factoryClass) { |
||||
try { |
||||
return doCreateConnectionFactory(factoryClass); |
||||
} |
||||
catch (Exception ex) { |
||||
throw new IllegalStateException("Unable to create ActiveMQConnectionFactory", ex); |
||||
} |
||||
} |
||||
|
||||
private <T extends ActiveMQConnectionFactory> T doCreateConnectionFactory(Class<T> factoryClass) throws Exception { |
||||
T factory = createConnectionFactoryInstance(factoryClass); |
||||
if (this.properties.getCloseTimeout() != null) { |
||||
factory.setCloseTimeout((int) this.properties.getCloseTimeout().toMillis()); |
||||
} |
||||
factory.setNonBlockingRedelivery(this.properties.isNonBlockingRedelivery()); |
||||
if (this.properties.getSendTimeout() != null) { |
||||
factory.setSendTimeout((int) this.properties.getSendTimeout().toMillis()); |
||||
} |
||||
Packages packages = this.properties.getPackages(); |
||||
if (packages.getTrustAll() != null) { |
||||
factory.setTrustAllPackages(packages.getTrustAll()); |
||||
} |
||||
if (!packages.getTrusted().isEmpty()) { |
||||
factory.setTrustedPackages(packages.getTrusted()); |
||||
} |
||||
customize(factory); |
||||
return factory; |
||||
} |
||||
|
||||
private <T extends ActiveMQConnectionFactory> T createConnectionFactoryInstance(Class<T> factoryClass) |
||||
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { |
||||
String brokerUrl = determineBrokerUrl(); |
||||
String user = this.properties.getUser(); |
||||
String password = this.properties.getPassword(); |
||||
if (StringUtils.hasLength(user) && StringUtils.hasLength(password)) { |
||||
return factoryClass.getConstructor(String.class, String.class, String.class) |
||||
.newInstance(user, password, brokerUrl); |
||||
} |
||||
return factoryClass.getConstructor(String.class).newInstance(brokerUrl); |
||||
} |
||||
|
||||
private void customize(ActiveMQConnectionFactory connectionFactory) { |
||||
for (ActiveMQConnectionFactoryCustomizer factoryCustomizer : this.factoryCustomizers) { |
||||
factoryCustomizer.customize(connectionFactory); |
||||
} |
||||
} |
||||
|
||||
String determineBrokerUrl() { |
||||
if (this.properties.getBrokerUrl() != null) { |
||||
return this.properties.getBrokerUrl(); |
||||
} |
||||
return DEFAULT_NETWORK_BROKER_URL; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
/* |
||||
* 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 java.time.Duration; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.boot.autoconfigure.jms.JmsPoolConnectionFactoryProperties; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty; |
||||
|
||||
/** |
||||
* Configuration properties for ActiveMQ. |
||||
* |
||||
* @author Greg Turnquist |
||||
* @author Stephane Nicoll |
||||
* @author Aurélien Leboulanger |
||||
* @author Venil Noronha |
||||
* @since 3.1.0 |
||||
*/ |
||||
@ConfigurationProperties(prefix = "spring.activemq") |
||||
public class ActiveMQProperties { |
||||
|
||||
/** |
||||
* URL of the ActiveMQ broker. Auto-generated by default. |
||||
*/ |
||||
private String brokerUrl; |
||||
|
||||
/** |
||||
* Login user of the broker. |
||||
*/ |
||||
private String user; |
||||
|
||||
/** |
||||
* Login password of the broker. |
||||
*/ |
||||
private String password; |
||||
|
||||
/** |
||||
* Time to wait before considering a close complete. |
||||
*/ |
||||
private Duration closeTimeout = Duration.ofSeconds(15); |
||||
|
||||
/** |
||||
* Whether to stop message delivery before re-delivering messages from a rolled back |
||||
* transaction. This implies that message order is not preserved when this is enabled. |
||||
*/ |
||||
private boolean nonBlockingRedelivery = false; |
||||
|
||||
/** |
||||
* Time to wait on message sends for a response. Set it to 0 to wait forever. |
||||
*/ |
||||
private Duration sendTimeout = Duration.ofMillis(0); |
||||
|
||||
@NestedConfigurationProperty |
||||
private final JmsPoolConnectionFactoryProperties pool = new JmsPoolConnectionFactoryProperties(); |
||||
|
||||
private final Packages packages = new Packages(); |
||||
|
||||
public String getBrokerUrl() { |
||||
return this.brokerUrl; |
||||
} |
||||
|
||||
public void setBrokerUrl(String brokerUrl) { |
||||
this.brokerUrl = brokerUrl; |
||||
} |
||||
|
||||
public String getUser() { |
||||
return this.user; |
||||
} |
||||
|
||||
public void setUser(String user) { |
||||
this.user = user; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return this.password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
|
||||
public Duration getCloseTimeout() { |
||||
return this.closeTimeout; |
||||
} |
||||
|
||||
public void setCloseTimeout(Duration closeTimeout) { |
||||
this.closeTimeout = closeTimeout; |
||||
} |
||||
|
||||
public boolean isNonBlockingRedelivery() { |
||||
return this.nonBlockingRedelivery; |
||||
} |
||||
|
||||
public void setNonBlockingRedelivery(boolean nonBlockingRedelivery) { |
||||
this.nonBlockingRedelivery = nonBlockingRedelivery; |
||||
} |
||||
|
||||
public Duration getSendTimeout() { |
||||
return this.sendTimeout; |
||||
} |
||||
|
||||
public void setSendTimeout(Duration sendTimeout) { |
||||
this.sendTimeout = sendTimeout; |
||||
} |
||||
|
||||
public JmsPoolConnectionFactoryProperties getPool() { |
||||
return this.pool; |
||||
} |
||||
|
||||
public Packages getPackages() { |
||||
return this.packages; |
||||
} |
||||
|
||||
public static class Packages { |
||||
|
||||
/** |
||||
* Whether to trust all packages. |
||||
*/ |
||||
private Boolean trustAll; |
||||
|
||||
/** |
||||
* Comma-separated list of specific packages to trust (when not trusting all |
||||
* packages). |
||||
*/ |
||||
private List<String> trusted = new ArrayList<>(); |
||||
|
||||
public Boolean getTrustAll() { |
||||
return this.trustAll; |
||||
} |
||||
|
||||
public void setTrustAll(Boolean trustAll) { |
||||
this.trustAll = trustAll; |
||||
} |
||||
|
||||
public List<String> getTrusted() { |
||||
return this.trusted; |
||||
} |
||||
|
||||
public void setTrusted(List<String> trusted) { |
||||
this.trusted = trusted; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
/* |
||||
* 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 java.util.stream.Collectors; |
||||
|
||||
import jakarta.jms.ConnectionFactory; |
||||
import jakarta.transaction.TransactionManager; |
||||
import org.apache.activemq.ActiveMQConnectionFactory; |
||||
import org.apache.activemq.ActiveMQXAConnectionFactory; |
||||
|
||||
import org.springframework.beans.factory.ObjectProvider; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.boot.jms.XAConnectionFactoryWrapper; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Primary; |
||||
|
||||
/** |
||||
* Configuration for ActiveMQ XA {@link ConnectionFactory}. |
||||
* |
||||
* @author Phillip Webb |
||||
* @author Aurélien Leboulanger |
||||
*/ |
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnClass(TransactionManager.class) |
||||
@ConditionalOnBean(XAConnectionFactoryWrapper.class) |
||||
@ConditionalOnMissingBean(ConnectionFactory.class) |
||||
class ActiveMQXAConnectionFactoryConfiguration { |
||||
|
||||
@Primary |
||||
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" }) |
||||
ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties, |
||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers, XAConnectionFactoryWrapper wrapper) |
||||
throws Exception { |
||||
ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(properties, |
||||
factoryCustomizers.orderedStream().collect(Collectors.toList())) |
||||
.createConnectionFactory(ActiveMQXAConnectionFactory.class); |
||||
return wrapper.wrapConnectionFactory(connectionFactory); |
||||
} |
||||
|
||||
@Bean |
||||
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", |
||||
matchIfMissing = true) |
||||
ActiveMQConnectionFactory nonXaJmsConnectionFactory(ActiveMQProperties properties, |
||||
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { |
||||
return new ActiveMQConnectionFactoryFactory(properties, |
||||
factoryCustomizers.orderedStream().collect(Collectors.toList())) |
||||
.createConnectionFactory(ActiveMQConnectionFactory.class); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,20 @@
@@ -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. |
||||
*/ |
||||
|
||||
/** |
||||
* Auto-configuration for ActiveMQ. |
||||
*/ |
||||
package org.springframework.boot.autoconfigure.jms.activemq; |
||||
@ -0,0 +1,264 @@
@@ -0,0 +1,264 @@
|
||||
/* |
||||
* 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 jakarta.jms.ConnectionFactory; |
||||
import org.apache.activemq.ActiveMQConnectionFactory; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory; |
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations; |
||||
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; |
||||
import org.springframework.boot.test.context.FilteredClassLoader; |
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.jms.connection.CachingConnectionFactory; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.mockingDetails; |
||||
|
||||
/** |
||||
* Tests for {@link ActiveMQAutoConfiguration}. |
||||
* |
||||
* @author Andy Wilkinson |
||||
* @author Aurélien Leboulanger |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class ActiveMQAutoConfigurationTests { |
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() |
||||
.withConfiguration(AutoConfigurations.of(ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class)); |
||||
|
||||
@Test |
||||
void brokerIsLocalhostByDefault() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> { |
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class).hasBean("jmsConnectionFactory"); |
||||
CachingConnectionFactory connectionFactory = context.getBean(CachingConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
assertThat(connectionFactory.getTargetConnectionFactory()).isInstanceOf(ActiveMQConnectionFactory.class); |
||||
assertThat(((ActiveMQConnectionFactory) connectionFactory.getTargetConnectionFactory()).getBrokerURL()) |
||||
.isEqualTo("tcp://localhost:61616"); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void configurationBacksOffWhenCustomConnectionFactoryExists() { |
||||
this.contextRunner.withUserConfiguration(CustomConnectionFactoryConfiguration.class) |
||||
.run((context) -> assertThat(mockingDetails(context.getBean(ConnectionFactory.class)).isMock()).isTrue()); |
||||
} |
||||
|
||||
@Test |
||||
void connectionFactoryIsCachedByDefault() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(CachingConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
CachingConnectionFactory connectionFactory = context.getBean(CachingConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
assertThat(connectionFactory.getTargetConnectionFactory()).isInstanceOf(ActiveMQConnectionFactory.class); |
||||
assertThat(connectionFactory.isCacheConsumers()).isFalse(); |
||||
assertThat(connectionFactory.isCacheProducers()).isTrue(); |
||||
assertThat(connectionFactory.getSessionCacheSize()).isEqualTo(1); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void connectionFactoryCachingCanBeCustomized() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) |
||||
.withPropertyValues("spring.jms.cache.consumers=true", "spring.jms.cache.producers=false", |
||||
"spring.jms.cache.session-cache-size=10") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(CachingConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
CachingConnectionFactory connectionFactory = context.getBean(CachingConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
assertThat(connectionFactory.isCacheConsumers()).isTrue(); |
||||
assertThat(connectionFactory.isCacheProducers()).isFalse(); |
||||
assertThat(connectionFactory.getSessionCacheSize()).isEqualTo(10); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void connectionFactoryCachingCanBeDisabled() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) |
||||
.withPropertyValues("spring.jms.cache.enabled=false") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(ActiveMQConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
ActiveMQConnectionFactory connectionFactory = context.getBean(ActiveMQConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
ActiveMQConnectionFactory defaultFactory = new ActiveMQConnectionFactory( |
||||
"vm://localhost?broker.persistent=false"); |
||||
assertThat(connectionFactory.getUserName()).isEqualTo(defaultFactory.getUserName()); |
||||
assertThat(connectionFactory.getPassword()).isEqualTo(defaultFactory.getPassword()); |
||||
assertThat(connectionFactory.getCloseTimeout()).isEqualTo(defaultFactory.getCloseTimeout()); |
||||
assertThat(connectionFactory.isNonBlockingRedelivery()) |
||||
.isEqualTo(defaultFactory.isNonBlockingRedelivery()); |
||||
assertThat(connectionFactory.getSendTimeout()).isEqualTo(defaultFactory.getSendTimeout()); |
||||
assertThat(connectionFactory.isTrustAllPackages()).isEqualTo(defaultFactory.isTrustAllPackages()); |
||||
assertThat(connectionFactory.getTrustedPackages()) |
||||
.containsExactly(StringUtils.toStringArray(defaultFactory.getTrustedPackages())); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void customConnectionFactoryIsApplied() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) |
||||
.withPropertyValues("spring.jms.cache.enabled=false", |
||||
"spring.activemq.brokerUrl=vm://localhost?useJmx=false&broker.persistent=false", |
||||
"spring.activemq.user=foo", "spring.activemq.password=bar", "spring.activemq.closeTimeout=500", |
||||
"spring.activemq.nonBlockingRedelivery=true", "spring.activemq.sendTimeout=1000", |
||||
"spring.activemq.packages.trust-all=false", "spring.activemq.packages.trusted=com.example.acme") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(ActiveMQConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
ActiveMQConnectionFactory connectionFactory = context.getBean(ActiveMQConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
assertThat(connectionFactory.getUserName()).isEqualTo("foo"); |
||||
assertThat(connectionFactory.getPassword()).isEqualTo("bar"); |
||||
assertThat(connectionFactory.getCloseTimeout()).isEqualTo(500); |
||||
assertThat(connectionFactory.isNonBlockingRedelivery()).isTrue(); |
||||
assertThat(connectionFactory.getSendTimeout()).isEqualTo(1000); |
||||
assertThat(connectionFactory.isTrustAllPackages()).isFalse(); |
||||
assertThat(connectionFactory.getTrustedPackages()).containsExactly("com.example.acme"); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void defaultPoolConnectionFactoryIsApplied() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) |
||||
.withPropertyValues("spring.activemq.pool.enabled=true") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(JmsPoolConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
JmsPoolConnectionFactory connectionFactory = context.getBean(JmsPoolConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
JmsPoolConnectionFactory defaultFactory = new JmsPoolConnectionFactory(); |
||||
assertThat(connectionFactory.isBlockIfSessionPoolIsFull()) |
||||
.isEqualTo(defaultFactory.isBlockIfSessionPoolIsFull()); |
||||
assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout()) |
||||
.isEqualTo(defaultFactory.getBlockIfSessionPoolIsFullTimeout()); |
||||
assertThat(connectionFactory.getConnectionIdleTimeout()) |
||||
.isEqualTo(defaultFactory.getConnectionIdleTimeout()); |
||||
assertThat(connectionFactory.getMaxConnections()).isEqualTo(defaultFactory.getMaxConnections()); |
||||
assertThat(connectionFactory.getMaxSessionsPerConnection()) |
||||
.isEqualTo(defaultFactory.getMaxSessionsPerConnection()); |
||||
assertThat(connectionFactory.getConnectionCheckInterval()) |
||||
.isEqualTo(defaultFactory.getConnectionCheckInterval()); |
||||
assertThat(connectionFactory.isUseAnonymousProducers()) |
||||
.isEqualTo(defaultFactory.isUseAnonymousProducers()); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void customPoolConnectionFactoryIsApplied() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) |
||||
.withPropertyValues("spring.activemq.pool.enabled=true", "spring.activemq.pool.blockIfFull=false", |
||||
"spring.activemq.pool.blockIfFullTimeout=64", "spring.activemq.pool.idleTimeout=512", |
||||
"spring.activemq.pool.maxConnections=256", "spring.activemq.pool.maxSessionsPerConnection=1024", |
||||
"spring.activemq.pool.timeBetweenExpirationCheck=2048", |
||||
"spring.activemq.pool.useAnonymousProducers=false") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(JmsPoolConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
JmsPoolConnectionFactory connectionFactory = context.getBean(JmsPoolConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
assertThat(connectionFactory.isBlockIfSessionPoolIsFull()).isFalse(); |
||||
assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout()).isEqualTo(64); |
||||
assertThat(connectionFactory.getConnectionIdleTimeout()).isEqualTo(512); |
||||
assertThat(connectionFactory.getMaxConnections()).isEqualTo(256); |
||||
assertThat(connectionFactory.getMaxSessionsPerConnection()).isEqualTo(1024); |
||||
assertThat(connectionFactory.getConnectionCheckInterval()).isEqualTo(2048); |
||||
assertThat(connectionFactory.isUseAnonymousProducers()).isFalse(); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void poolConnectionFactoryConfiguration() { |
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) |
||||
.withPropertyValues("spring.activemq.pool.enabled:true") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(JmsPoolConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
ConnectionFactory factory = context.getBean(ConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(factory); |
||||
assertThat(factory).isInstanceOf(JmsPoolConnectionFactory.class); |
||||
context.getSourceApplicationContext().close(); |
||||
assertThat(factory.createConnection()).isNull(); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void cachingConnectionFactoryNotOnTheClasspathThenSimpleConnectionFactoryAutoConfigured() { |
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(CachingConnectionFactory.class)) |
||||
.withPropertyValues("spring.activemq.pool.enabled=false", "spring.jms.cache.enabled=false") |
||||
.run((context) -> { |
||||
assertThat(context).hasSingleBean(ConnectionFactory.class) |
||||
.hasSingleBean(ActiveMQConnectionFactory.class) |
||||
.hasBean("jmsConnectionFactory"); |
||||
ActiveMQConnectionFactory connectionFactory = context.getBean(ActiveMQConnectionFactory.class); |
||||
assertThat(context.getBean("jmsConnectionFactory")).isSameAs(connectionFactory); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
void cachingConnectionFactoryNotOnTheClasspathAndCacheEnabledThenSimpleConnectionFactoryNotConfigured() { |
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(CachingConnectionFactory.class)) |
||||
.withPropertyValues("spring.activemq.pool.enabled=false", "spring.jms.cache.enabled=true") |
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConnectionFactory.class) |
||||
.doesNotHaveBean(ActiveMQConnectionFactory.class) |
||||
.doesNotHaveBean("jmsConnectionFactory")); |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class EmptyConfiguration { |
||||
|
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class CustomConnectionFactoryConfiguration { |
||||
|
||||
@Bean |
||||
ConnectionFactory connectionFactory() { |
||||
return mock(ConnectionFactory.class); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class CustomizerConfiguration { |
||||
|
||||
@Bean |
||||
ActiveMQConnectionFactoryCustomizer activeMQConnectionFactoryCustomizer() { |
||||
return (factory) -> { |
||||
factory.setBrokerURL("vm://localhost?useJmx=false&broker.persistent=false"); |
||||
factory.setUserName("foobar"); |
||||
}; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* 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 java.util.Collections; |
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link ActiveMQProperties} and {@link ActiveMQConnectionFactoryFactory}. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @author Aurélien Leboulanger |
||||
* @author Venil Noronha |
||||
*/ |
||||
class ActiveMQPropertiesTests { |
||||
|
||||
private static final String DEFAULT_NETWORK_BROKER_URL = "tcp://localhost:61616"; |
||||
|
||||
private final ActiveMQProperties properties = new ActiveMQProperties(); |
||||
|
||||
@Test |
||||
void getBrokerUrlIsLocalhostByDefault() { |
||||
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo(DEFAULT_NETWORK_BROKER_URL); |
||||
} |
||||
|
||||
@Test |
||||
void getBrokerUrlUseExplicitBrokerUrl() { |
||||
this.properties.setBrokerUrl("tcp://activemq.example.com:71717"); |
||||
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo("tcp://activemq.example.com:71717"); |
||||
} |
||||
|
||||
@Test |
||||
void setTrustAllPackages() { |
||||
this.properties.getPackages().setTrustAll(true); |
||||
assertThat(createFactory(this.properties).createConnectionFactory(ActiveMQConnectionFactory.class) |
||||
.isTrustAllPackages()).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
void setTrustedPackages() { |
||||
this.properties.getPackages().setTrustAll(false); |
||||
this.properties.getPackages().getTrusted().add("trusted.package"); |
||||
ActiveMQConnectionFactory factory = createFactory(this.properties) |
||||
.createConnectionFactory(ActiveMQConnectionFactory.class); |
||||
assertThat(factory.isTrustAllPackages()).isFalse(); |
||||
assertThat(factory.getTrustedPackages().size()).isEqualTo(1); |
||||
assertThat(factory.getTrustedPackages().get(0)).isEqualTo("trusted.package"); |
||||
} |
||||
|
||||
private ActiveMQConnectionFactoryFactory createFactory(ActiveMQProperties properties) { |
||||
return new ActiveMQConnectionFactoryFactory(properties, Collections.emptyList()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
plugins { |
||||
id "org.springframework.boot.starter" |
||||
} |
||||
|
||||
description = "Starter for JMS messaging using Apache ActiveMQ" |
||||
|
||||
dependencies { |
||||
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter")) |
||||
api("org.springframework:spring-jms") |
||||
api("org.apache.activemq:activemq-client-jakarta") |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
/* |
||||
* 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.testsupport.testcontainers; |
||||
|
||||
import org.testcontainers.containers.GenericContainer; |
||||
|
||||
/** |
||||
* A {@link GenericContainer} for ActiveMQ. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 3.1.0 |
||||
*/ |
||||
public class ActiveMQContainer extends GenericContainer<ActiveMQContainer> { |
||||
|
||||
private static final int DEFAULT_PORT = 61616; |
||||
|
||||
public ActiveMQContainer() { |
||||
super(DockerImageNames.activeMq()); |
||||
addExposedPorts(DEFAULT_PORT); |
||||
} |
||||
|
||||
/** |
||||
* Return the broker URL to use. |
||||
* @return the broker url of the ActiveMQ instance |
||||
*/ |
||||
public String getBrokerUrl() { |
||||
return String.format("tcp://" + getHost() + ":" + getMappedPort(DEFAULT_PORT)); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
plugins { |
||||
id "java" |
||||
id "org.springframework.boot.conventions" |
||||
} |
||||
|
||||
description = "Spring Boot Actuator ActiveMQ smoke test" |
||||
|
||||
dependencies { |
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-activemq")) |
||||
|
||||
testImplementation("org.testcontainers:testcontainers") |
||||
testImplementation("org.testcontainers:junit-jupiter") |
||||
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-tools:spring-boot-test-support")) |
||||
} |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
/* |
||||
* 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 smoketest.activemq; |
||||
|
||||
import org.springframework.jms.annotation.JmsListener; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
public class Consumer { |
||||
|
||||
@JmsListener(destination = "sample.queue") |
||||
public void receiveQueue(String text) { |
||||
System.out.println(text); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* 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 smoketest.activemq; |
||||
|
||||
import jakarta.jms.Queue; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.CommandLineRunner; |
||||
import org.springframework.jms.core.JmsMessagingTemplate; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
public class Producer implements CommandLineRunner { |
||||
|
||||
@Autowired |
||||
private JmsMessagingTemplate jmsMessagingTemplate; |
||||
|
||||
@Autowired |
||||
private Queue queue; |
||||
|
||||
@Override |
||||
public void run(String... args) throws Exception { |
||||
send("Sample message"); |
||||
System.out.println("Message was sent to the Queue"); |
||||
} |
||||
|
||||
public void send(String msg) { |
||||
this.jmsMessagingTemplate.convertAndSend(this.queue, msg); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* 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 smoketest.activemq; |
||||
|
||||
import jakarta.jms.Queue; |
||||
import org.apache.activemq.command.ActiveMQQueue; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.jms.annotation.EnableJms; |
||||
|
||||
@SpringBootApplication |
||||
@EnableJms |
||||
public class SampleActiveMQApplication { |
||||
|
||||
@Bean |
||||
public Queue queue() { |
||||
return new ActiveMQQueue("sample.queue"); |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(SampleActiveMQApplication.class, args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
spring.activemq.pool.enabled=false |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
/* |
||||
* 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 smoketest.activemq; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
import org.testcontainers.junit.jupiter.Container; |
||||
import org.testcontainers.junit.jupiter.Testcontainers; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.boot.test.system.CapturedOutput; |
||||
import org.springframework.boot.test.system.OutputCaptureExtension; |
||||
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; |
||||
|
||||
/** |
||||
* Integration tests for demo application. |
||||
* |
||||
* @author Eddú Meléndez |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
@SpringBootTest |
||||
@Testcontainers(disabledWithoutDocker = true) |
||||
@ExtendWith(OutputCaptureExtension.class) |
||||
class SampleActiveMqTests { |
||||
|
||||
@Container |
||||
private static final ActiveMQContainer container = new ActiveMQContainer(); |
||||
|
||||
@DynamicPropertySource |
||||
static void activeMqProperties(DynamicPropertyRegistry registry) { |
||||
registry.add("spring.activemq.broker-url", container::getBrokerUrl); |
||||
} |
||||
|
||||
@Autowired |
||||
private Producer producer; |
||||
|
||||
@Test |
||||
void sendSimpleMessage(CapturedOutput output) throws InterruptedException { |
||||
this.producer.send("Test message"); |
||||
Thread.sleep(1000L); |
||||
assertThat(output).contains("Test message"); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue