Remove support for Apache ActiveMQ

Closes gh-28591
pull/28862/head
Andy Wilkinson 3 years ago
parent a3c4059ee8
commit 63492507b4

@ -80,10 +80,6 @@ dependencies {
optional("jakarta.persistence:jakarta.persistence-api") optional("jakarta.persistence:jakarta.persistence-api")
optional("jakarta.servlet:jakarta.servlet-api") optional("jakarta.servlet:jakarta.servlet-api")
optional("javax.cache:cache-api") optional("javax.cache:cache-api")
optional("org.apache.activemq:activemq-broker") {
exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_1.1_spec"
exclude group: "org.apache.geronimo.specs", module: "geronimo-j2ee-management_1.1_spec"
}
optional("org.apache.commons:commons-dbcp2") { optional("org.apache.commons:commons-dbcp2") {
exclude group: "commons-logging", module: "commons-logging" exclude group: "commons-logging", module: "commons-logging"
} }
@ -164,6 +160,17 @@ dependencies {
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_4.0_spec" exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_4.0_spec"
} }
testImplementation("jakarta.xml.bind:jakarta.xml.bind-api") testImplementation("jakarta.xml.bind:jakarta.xml.bind-api")
testImplementation("org.apache.activemq:artemis-jms-client") {
exclude group: "commons-logging", module: "commons-logging"
exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec"
exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec"
}
testImplementation("org.apache.activemq:artemis-jms-server") {
exclude group: "commons-logging", module: "commons-logging"
exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec"
exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec"
exclude group: "org.apache.geronimo.specs", module: "geronimo-jta_1.1_spec"
}
testImplementation("org.apache.logging.log4j:log4j-to-slf4j") testImplementation("org.apache.logging.log4j:log4j-to-slf4j")
testImplementation("org.aspectj:aspectjrt") testImplementation("org.aspectj:aspectjrt")
testImplementation("org.assertj:assertj-core") testImplementation("org.assertj:assertj-core")

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,7 +29,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration; import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -44,7 +43,7 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnClass(ConnectionFactory.class) @ConditionalOnClass(ConnectionFactory.class)
@ConditionalOnBean(ConnectionFactory.class) @ConditionalOnBean(ConnectionFactory.class)
@ConditionalOnEnabledHealthIndicator("jms") @ConditionalOnEnabledHealthIndicator("jms")
@AutoConfigureAfter({ ActiveMQAutoConfiguration.class, ArtemisAutoConfiguration.class }) @AutoConfigureAfter(ArtemisAutoConfiguration.class)
public class JmsHealthContributorAutoConfiguration public class JmsHealthContributorAutoConfiguration
extends CompositeHealthContributorConfiguration<JmsHealthIndicator, ConnectionFactory> { extends CompositeHealthContributorConfiguration<JmsHealthIndicator, ConnectionFactory> {

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,7 +22,7 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAu
import org.springframework.boot.actuate.jms.JmsHealthIndicator; import org.springframework.boot.actuate.jms.JmsHealthIndicator;
import org.springframework.boot.actuate.ldap.LdapHealthIndicator; import org.springframework.boot.actuate.ldap.LdapHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration; import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class JmsHealthContributorAutoConfigurationTests { class JmsHealthContributorAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ActiveMQAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(ArtemisAutoConfiguration.class,
JmsHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class)); JmsHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
@Test @Test

@ -51,10 +51,6 @@ dependencies {
optional("jakarta.ws.rs:jakarta.ws.rs-api") optional("jakarta.ws.rs:jakarta.ws.rs-api")
optional("javax.cache:cache-api") optional("javax.cache:cache-api")
optional("javax.money:money-api") optional("javax.money:money-api")
optional("org.apache.activemq:activemq-broker") {
exclude group: "org.apache.geronimo.specs", module: "geronimo-j2ee-management_1.1_spec"
exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_1.1_spec"
}
optional("org.apache.activemq:artemis-jms-client") { optional("org.apache.activemq:artemis-jms-client") {
exclude group: "commons-logging", module: "commons-logging" exclude group: "commons-logging", module: "commons-logging"
exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec" exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec"

@ -1,53 +0,0 @@
/*
* Copyright 2012-2019 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 javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.Configuration;
import org.springframework.context.annotation.Import;
/**
* {@link EnableAutoConfiguration Auto-configuration} to integrate with an ActiveMQ
* broker. Validates that the classpath contain the necessary classes before starting an
* embedded broker.
*
* @author Stephane Nicoll
* @author Phillip Webb
* @since 1.1.0
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(JmsAutoConfiguration.class)
@AutoConfigureAfter({ JndiConnectionFactoryAutoConfiguration.class })
@ConditionalOnClass({ ConnectionFactory.class, ActiveMQConnectionFactory.class })
@ConditionalOnMissingBean(ConnectionFactory.class)
@EnableConfigurationProperties({ ActiveMQProperties.class, JmsProperties.class })
@Import({ ActiveMQXAConnectionFactoryConfiguration.class, ActiveMQConnectionFactoryConfiguration.class })
public class ActiveMQAutoConfiguration {
}

@ -1,108 +0,0 @@
/*
* Copyright 2012-2020 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 javax.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);
}
}
}

@ -1,37 +0,0 @@
/*
* Copyright 2012-2019 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 1.5.5
*/
@FunctionalInterface
public interface ActiveMQConnectionFactoryCustomizer {
/**
* Customize the {@link ActiveMQConnectionFactory}.
* @param factory the factory to customize
*/
void customize(ActiveMQConnectionFactory factory);
}

@ -1,110 +0,0 @@
/*
* Copyright 2012-2019 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_EMBEDDED_BROKER_URL = "vm://localhost?broker.persistent=false";
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();
}
if (this.properties.isInMemory()) {
return DEFAULT_EMBEDDED_BROKER_URL;
}
return DEFAULT_NETWORK_BROKER_URL;
}
}

@ -1,176 +0,0 @@
/*
* Copyright 2012-2019 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 1.0.0
*/
@ConfigurationProperties(prefix = "spring.activemq")
public class ActiveMQProperties {
/**
* URL of the ActiveMQ broker. Auto-generated by default.
*/
private String brokerUrl;
/**
* Whether the default broker URL should be in memory. Ignored if an explicit broker
* has been specified.
*/
private boolean inMemory = true;
/**
* 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 boolean isInMemory() {
return this.inMemory;
}
public void setInMemory(boolean inMemory) {
this.inMemory = inMemory;
}
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;
}
}
}

@ -1,70 +0,0 @@
/*
* Copyright 2012-2019 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 javax.jms.ConnectionFactory;
import javax.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);
}
}

@ -1,20 +0,0 @@
/*
* Copyright 2012-2019 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;

@ -21,7 +21,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration; import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -38,8 +37,8 @@ import org.springframework.context.annotation.Import;
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(javax.transaction.Transaction.class) @ConditionalOnClass(javax.transaction.Transaction.class)
@ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true)
@AutoConfigureBefore({ XADataSourceAutoConfiguration.class, ActiveMQAutoConfiguration.class, @AutoConfigureBefore({ XADataSourceAutoConfiguration.class, ArtemisAutoConfiguration.class,
ArtemisAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) HibernateJpaAutoConfiguration.class })
@Import(JndiJtaConfiguration.class) @Import(JndiJtaConfiguration.class)
public class JtaAutoConfiguration { public class JtaAutoConfiguration {

@ -87,7 +87,6 @@ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConf
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\

@ -16,17 +16,18 @@
package org.springframework.boot.autoconfigure.jms; package org.springframework.boot.autoconfigure.jms;
import java.io.IOException;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import javax.jms.ExceptionListener; import javax.jms.ExceptionListener;
import javax.jms.Session; import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration; import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -60,12 +61,8 @@ import static org.mockito.Mockito.mock;
*/ */
class JmsAutoConfigurationTests { class JmsAutoConfigurationTests {
private static final String ACTIVEMQ_EMBEDDED_URL = "vm://localhost?broker.persistent=false";
private static final String ACTIVEMQ_NETWORK_URL = "tcp://localhost:61616";
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(ArtemisAutoConfiguration.class, JmsAutoConfiguration.class));
@Test @Test
void testDefaultJmsConfiguration() { void testDefaultJmsConfiguration() {
@ -81,15 +78,15 @@ class JmsAutoConfigurationTests {
JmsMessagingTemplate messagingTemplate = loaded.getBean(JmsMessagingTemplate.class); JmsMessagingTemplate messagingTemplate = loaded.getBean(JmsMessagingTemplate.class);
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate);
assertThat(getBrokerUrl(factory)).isEqualTo(ACTIVEMQ_EMBEDDED_URL); assertThat(getBrokerUrl(factory)).startsWith("vm://");
assertThat(loaded.containsBean("jmsListenerContainerFactory")).isTrue(); assertThat(loaded.containsBean("jmsListenerContainerFactory")).isTrue();
} }
@Test @Test
void testConnectionFactoryBackOff() { void testConnectionFactoryBackOff() {
this.contextRunner.withUserConfiguration(TestConfiguration2.class) this.contextRunner.withUserConfiguration(TestConfiguration2.class)
.run((context) -> assertThat(context.getBean(ActiveMQConnectionFactory.class).getBrokerURL()) .run((context) -> assertThat(context.getBeansOfType(ActiveMQConnectionFactory.class))
.isEqualTo("foobar")); .containsOnlyKeys("customConnectionFactory"));
} }
@Test @Test
@ -112,10 +109,10 @@ class JmsAutoConfigurationTests {
.run(this::testJmsTemplateBackOffEverything); .run(this::testJmsTemplateBackOffEverything);
} }
private void testJmsTemplateBackOffEverything(AssertableApplicationContext loaded) { private void testJmsTemplateBackOffEverything(AssertableApplicationContext loaded) throws IOException {
JmsTemplate jmsTemplate = loaded.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = loaded.getBean(JmsTemplate.class);
assertThat(jmsTemplate.getPriority()).isEqualTo(999); assertThat(jmsTemplate.getPriority()).isEqualTo(999);
assertThat(loaded.getBean(ActiveMQConnectionFactory.class).getBrokerURL()).isEqualTo("foobar"); assertThat(loaded.getBeansOfType(ActiveMQConnectionFactory.class)).containsOnlyKeys("customConnectionFactory");
JmsMessagingTemplate messagingTemplate = loaded.getBean(JmsMessagingTemplate.class); JmsMessagingTemplate messagingTemplate = loaded.getBean(JmsMessagingTemplate.class);
assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar");
assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate);
@ -320,80 +317,14 @@ class JmsAutoConfigurationTests {
}); });
} }
@Test
void testActiveMQOverriddenStandalone() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.activemq.inMemory:false").run((context) -> {
assertThat(context).hasSingleBean(JmsTemplate.class);
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
ConnectionFactory factory = context.getBean(ConnectionFactory.class);
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
assertThat(getBrokerUrl((CachingConnectionFactory) factory)).isEqualTo(ACTIVEMQ_NETWORK_URL);
});
}
@Test
void testActiveMQOverriddenRemoteHost() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.activemq.brokerUrl:tcp://remote-host:10000").run((context) -> {
assertThat(context).hasSingleBean(JmsTemplate.class);
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
ConnectionFactory factory = context.getBean(ConnectionFactory.class);
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
assertThat(getBrokerUrl((CachingConnectionFactory) factory)).isEqualTo("tcp://remote-host:10000");
});
}
private String getBrokerUrl(CachingConnectionFactory connectionFactory) { private String getBrokerUrl(CachingConnectionFactory connectionFactory) {
assertThat(connectionFactory.getTargetConnectionFactory()).isInstanceOf(ActiveMQConnectionFactory.class); assertThat(connectionFactory.getTargetConnectionFactory()).isInstanceOf(ActiveMQConnectionFactory.class);
return ((ActiveMQConnectionFactory) connectionFactory.getTargetConnectionFactory()).getBrokerURL(); try {
} return ((ActiveMQConnectionFactory) connectionFactory.getTargetConnectionFactory()).toURI().toString();
}
@Test catch (IOException ex) {
void testActiveMQOverriddenPool() { throw new RuntimeException(ex);
this.contextRunner.withUserConfiguration(TestConfiguration.class) }
.withPropertyValues("spring.activemq.pool.enabled:true").run((context) -> {
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
JmsPoolConnectionFactory pool = context.getBean(JmsPoolConnectionFactory.class);
assertThat(jmsTemplate).isNotNull();
assertThat(pool).isNotNull();
assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory());
ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool.getConnectionFactory();
assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL);
});
}
@Test
void testActiveMQOverriddenPoolAndStandalone() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.activemq.pool.enabled:true", "spring.activemq.inMemory:false")
.run((context) -> {
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
JmsPoolConnectionFactory pool = context.getBean(JmsPoolConnectionFactory.class);
assertThat(jmsTemplate).isNotNull();
assertThat(pool).isNotNull();
assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory());
ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool.getConnectionFactory();
assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL);
});
}
@Test
void testActiveMQOverriddenPoolAndRemoteServer() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.activemq.pool.enabled:true",
"spring.activemq.brokerUrl:tcp://remote-host:10000")
.run((context) -> {
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
JmsPoolConnectionFactory pool = context.getBean(JmsPoolConnectionFactory.class);
assertThat(jmsTemplate).isNotNull();
assertThat(pool).isNotNull();
assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory());
ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool.getConnectionFactory();
assertThat(factory.getBrokerURL()).isEqualTo("tcp://remote-host:10000");
});
} }
@Test @Test
@ -413,12 +344,8 @@ class JmsAutoConfigurationTests {
static class TestConfiguration2 { static class TestConfiguration2 {
@Bean @Bean
ConnectionFactory connectionFactory() { ConnectionFactory customConnectionFactory() {
return new ActiveMQConnectionFactory() { return new ActiveMQConnectionFactory();
{
setBrokerURL("foobar");
}
};
} }
} }

@ -1,253 +0,0 @@
/*
* Copyright 2012-2020 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 javax.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 brokerIsEmbeddedByDefault() {
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("vm://localhost?broker.persistent=false");
});
}
@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");
};
}
}
}

@ -1,87 +0,0 @@
/*
* Copyright 2012-2019 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_EMBEDDED_BROKER_URL = "vm://localhost?broker.persistent=false";
private static final String DEFAULT_NETWORK_BROKER_URL = "tcp://localhost:61616";
private final ActiveMQProperties properties = new ActiveMQProperties();
@Test
void getBrokerUrlIsInMemoryByDefault() {
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo(DEFAULT_EMBEDDED_BROKER_URL);
}
@Test
void getBrokerUrlUseExplicitBrokerUrl() {
this.properties.setBrokerUrl("vm://foo-bar");
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo("vm://foo-bar");
}
@Test
void getBrokerUrlWithInMemorySetToFalse() {
this.properties.setInMemory(false);
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo(DEFAULT_NETWORK_BROKER_URL);
}
@Test
void getExplicitBrokerUrlAlwaysWins() {
this.properties.setBrokerUrl("vm://foo-bar");
this.properties.setInMemory(false);
assertThat(createFactory(this.properties).determineBrokerUrl()).isEqualTo("vm://foo-bar");
}
@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());
}
}

@ -14,45 +14,6 @@ bom {
issueLabels = ["type: dependency-upgrade"] issueLabels = ["type: dependency-upgrade"]
} }
} }
library("ActiveMQ", "5.16.3") {
group("org.apache.activemq") {
modules = [
"activemq-amqp",
"activemq-blueprint",
"activemq-broker",
"activemq-camel",
"activemq-client",
"activemq-console" {
exclude group: "commons-logging", module: "commons-logging"
},
"activemq-http",
"activemq-jaas",
"activemq-jdbc-store",
"activemq-jms-pool",
"activemq-kahadb-store",
"activemq-karaf",
"activemq-leveldb-store" {
exclude group: "commons-logging", module: "commons-logging"
},
"activemq-log4j-appender",
"activemq-mqtt",
"activemq-openwire-generator",
"activemq-openwire-legacy",
"activemq-osgi",
"activemq-partition",
"activemq-pool",
"activemq-ra",
"activemq-run",
"activemq-runtime-config",
"activemq-shiro",
"activemq-spring" {
exclude group: "commons-logging", module: "commons-logging"
},
"activemq-stomp",
"activemq-web"
]
}
}
library("ANTLR2", "2.7.7") { library("ANTLR2", "2.7.7") {
prohibit("20030911") { prohibit("20030911") {
because "it is old version that used a different versioning scheme" because "it is old version that used a different versioning scheme"

@ -7,67 +7,6 @@ Spring Boot also auto-configures the necessary infrastructure to send and receiv
[[messaging.jms.activemq]]
=== ActiveMQ Support
When https://activemq.apache.org/[ActiveMQ] is available on the classpath, Spring Boot can also configure a `ConnectionFactory`.
If the broker is present, an embedded broker is automatically started and configured (provided no broker URL is specified through configuration and the embedded broker is not disabled in the configuration).
NOTE: If you use `spring-boot-starter-activemq`, the necessary dependencies to connect or embed an ActiveMQ instance are provided, as is the Spring infrastructure to integrate with JMS.
ActiveMQ configuration is controlled by external configuration properties in `+spring.activemq.*+`.
By default, ActiveMQ is auto-configured to use the https://activemq.apache.org/vm-transport-reference.html[VM transport], which starts a broker embedded in the same JVM instance.
You can disable the embedded broker by configuring the configprop:spring.activemq.in-memory[] property, as shown in the following example:
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
----
spring:
activemq:
in-memory: false
----
The embedded broker will also be disabled if you configure the broker URL, as shown in the following example:
[source,yaml,indent=0,configprops,configblocks]
----
spring:
activemq:
broker-url: "tcp://192.168.1.210:9876"
user: "admin"
password: "secret"
----
If you want to take full control over the embedded broker, see https://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html[the ActiveMQ documentation] for further information.
By default, a `CachingConnectionFactory` wraps the native `ConnectionFactory` with sensible settings that you can control by external configuration properties in `+spring.jms.*+`:
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
----
spring:
jms:
cache:
session-cache-size: 5
----
If you'd rather use native pooling, you can do so by adding a dependency to `org.messaginghub:pooled-jms` and configuring the `JmsPoolConnectionFactory` accordingly, as shown in the following example:
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
----
spring:
activemq:
pool:
enabled: true
max-connections: 50
----
TIP: See {spring-boot-autoconfigure-module-code}/jms/activemq/ActiveMQProperties.java[`ActiveMQProperties`] for more of the supported options.
You can also register an arbitrary number of beans that implement `ActiveMQConnectionFactoryCustomizer` for more advanced customizations.
By default, ActiveMQ creates a destination if it does not yet exist so that destinations are resolved against their provided names.
[[messaging.jms.artemis]] [[messaging.jms.artemis]]
=== ActiveMQ Artemis Support === ActiveMQ Artemis Support
Spring Boot can auto-configure a `ConnectionFactory` when it detects that https://activemq.apache.org/components/artemis/[ActiveMQ Artemis] is available on the classpath. Spring Boot can auto-configure a `ConnectionFactory` when it detects that https://activemq.apache.org/components/artemis/[ActiveMQ Artemis] is available on the classpath.

@ -1,16 +0,0 @@
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-broker") {
exclude group: "org.apache.geronimo.specs", module: "geronimo-j2ee-management_1.1_spec"
exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_1.1_spec"
}
api("jakarta.jms:jakarta.jms-api")
api("jakarta.management.j2ee:jakarta.management.j2ee-api")
}

@ -1,12 +0,0 @@
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(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
}

@ -1,30 +0,0 @@
/*
* Copyright 2012-2019 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);
}
}

@ -1,45 +0,0 @@
/*
* Copyright 2012-2019 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 javax.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);
}
}

@ -1,41 +0,0 @@
/*
* Copyright 2012-2019 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 javax.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);
}
}

@ -1,48 +0,0 @@
/*
* Copyright 2012-2019 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.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 static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for demo application.
*
* @author Eddú Meléndez
*/
@SpringBootTest
@ExtendWith(OutputCaptureExtension.class)
class SampleActiveMqTests {
@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…
Cancel
Save