parent
9392ff59f7
commit
89e79e826e
|
|
@ -145,6 +145,17 @@ dependencies {
|
|||
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.3_spec"
|
||||
}
|
||||
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.aspectj:aspectjrt")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
|
|
|
|||
|
|
@ -24,10 +24,12 @@ import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthCont
|
|||
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthContributor;
|
||||
import org.springframework.boot.actuate.jms.JmsHealthIndicator;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
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.jms.artemis.ArtemisAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
|
@ -41,6 +43,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
@ConditionalOnClass(ConnectionFactory.class)
|
||||
@ConditionalOnBean(ConnectionFactory.class)
|
||||
@ConditionalOnEnabledHealthIndicator("jms")
|
||||
@AutoConfigureAfter(ArtemisAutoConfiguration.class)
|
||||
public class JmsHealthContributorAutoConfiguration
|
||||
extends CompositeHealthContributorConfiguration<JmsHealthIndicator, ConnectionFactory> {
|
||||
|
||||
|
|
|
|||
|
|
@ -16,20 +16,16 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure.jms;
|
||||
|
||||
import jakarta.jms.ConnectionFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration;
|
||||
import org.springframework.boot.actuate.jms.JmsHealthIndicator;
|
||||
import org.springframework.boot.actuate.ldap.LdapHealthIndicator;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link JmsHealthContributorAutoConfiguration}.
|
||||
|
|
@ -39,9 +35,8 @@ import static org.mockito.Mockito.mock;
|
|||
class JmsHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JmsHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class))
|
||||
.withUserConfiguration(TestConfiguration.class);
|
||||
.withConfiguration(AutoConfigurations.of(ArtemisAutoConfiguration.class,
|
||||
JmsHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
|
|
@ -54,14 +49,4 @@ class JmsHealthContributorAutoConfigurationTests {
|
|||
.run((context) -> assertThat(context).doesNotHaveBean(LdapHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
ConnectionFactory connectionFactory() {
|
||||
return mock(ConnectionFactory.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,17 @@ dependencies {
|
|||
optional("jakarta.ws.rs:jakarta.ws.rs-api")
|
||||
optional("javax.cache:cache-api")
|
||||
optional("javax.money:money-api")
|
||||
optional("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"
|
||||
}
|
||||
optional("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"
|
||||
}
|
||||
optional("org.apache.commons:commons-dbcp2") {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
|
||||
import org.apache.activemq.artemis.jms.client.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 Artemis broker.
|
||||
* If the necessary classes are present, embed the broker in the application by default.
|
||||
* Otherwise, connect to a broker available on the local machine with the default
|
||||
* settings.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
* @see ArtemisProperties
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigureBefore(JmsAutoConfiguration.class)
|
||||
@AutoConfigureAfter({ JndiConnectionFactoryAutoConfiguration.class })
|
||||
@ConditionalOnClass({ ConnectionFactory.class, ActiveMQConnectionFactory.class })
|
||||
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||
@EnableConfigurationProperties({ ArtemisProperties.class, JmsProperties.class })
|
||||
@Import({ ArtemisEmbeddedServerConfiguration.class, ArtemisXAConnectionFactoryConfiguration.class,
|
||||
ArtemisConnectionFactoryConfiguration.class })
|
||||
public class ArtemisAutoConfiguration {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
|
||||
|
||||
/**
|
||||
* Callback interface that can be implemented by beans wishing to customize the Artemis
|
||||
* JMS server {@link Configuration} before it is used by an auto-configured
|
||||
* {@link EmbeddedActiveMQ} instance.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
* @see ArtemisAutoConfiguration
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ArtemisConfigurationCustomizer {
|
||||
|
||||
/**
|
||||
* Customize the configuration.
|
||||
* @param configuration the configuration to customize
|
||||
*/
|
||||
void customize(Configuration configuration);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
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 Artemis {@link ConnectionFactory}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||
class ArtemisConnectionFactoryConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(CachingConnectionFactory.class)
|
||||
@ConditionalOnProperty(prefix = "spring.artemis.pool", name = "enabled", havingValue = "false",
|
||||
matchIfMissing = true)
|
||||
static class SimpleConnectionFactoryConfiguration {
|
||||
|
||||
private final ArtemisProperties properties;
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
SimpleConnectionFactoryConfiguration(ArtemisProperties properties, ListableBeanFactory beanFactory) {
|
||||
this.properties = properties;
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Bean(name = "jmsConnectionFactory")
|
||||
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
CachingConnectionFactory cachingJmsConnectionFactory(JmsProperties jmsProperties) {
|
||||
JmsProperties.Cache cacheProperties = jmsProperties.getCache();
|
||||
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(createConnectionFactory());
|
||||
connectionFactory.setCacheConsumers(cacheProperties.isConsumers());
|
||||
connectionFactory.setCacheProducers(cacheProperties.isProducers());
|
||||
connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize());
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
@Bean(name = "jmsConnectionFactory")
|
||||
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false")
|
||||
ActiveMQConnectionFactory jmsConnectionFactory() {
|
||||
return createConnectionFactory();
|
||||
}
|
||||
|
||||
private ActiveMQConnectionFactory createConnectionFactory() {
|
||||
return new ArtemisConnectionFactoryFactory(this.beanFactory, this.properties)
|
||||
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class })
|
||||
@ConditionalOnProperty(prefix = "spring.artemis.pool", name = "enabled", havingValue = "true")
|
||||
static class PooledConnectionFactoryConfiguration {
|
||||
|
||||
@Bean(destroyMethod = "stop")
|
||||
JmsPoolConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, ArtemisProperties properties) {
|
||||
ActiveMQConnectionFactory connectionFactory = new ArtemisConnectionFactoryFactory(beanFactory, properties)
|
||||
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
||||
return new JmsPoolConnectionFactoryFactory(properties.getPool())
|
||||
.createPooledConnectionFactory(connectionFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||
import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Factory to create an Artemis {@link ActiveMQConnectionFactory} instance from properties
|
||||
* defined in {@link ArtemisProperties}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @author Justin Bertram
|
||||
*/
|
||||
class ArtemisConnectionFactoryFactory {
|
||||
|
||||
private static final String DEFAULT_BROKER_URL = "tcp://localhost:61616";
|
||||
|
||||
static final String[] EMBEDDED_JMS_CLASSES = { "org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS",
|
||||
"org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ" };
|
||||
|
||||
private final ArtemisProperties properties;
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
ArtemisConnectionFactoryFactory(ListableBeanFactory beanFactory, ArtemisProperties properties) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(properties, "Properties must not be null");
|
||||
this.beanFactory = beanFactory;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
<T extends ActiveMQConnectionFactory> T createConnectionFactory(Class<T> factoryClass) {
|
||||
try {
|
||||
startEmbeddedJms();
|
||||
return doCreateConnectionFactory(factoryClass);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to create ActiveMQConnectionFactory", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void startEmbeddedJms() {
|
||||
for (String embeddedJmsClass : EMBEDDED_JMS_CLASSES) {
|
||||
if (ClassUtils.isPresent(embeddedJmsClass, null)) {
|
||||
try {
|
||||
this.beanFactory.getBeansOfType(Class.forName(embeddedJmsClass));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends ActiveMQConnectionFactory> T doCreateConnectionFactory(Class<T> factoryClass) throws Exception {
|
||||
ArtemisMode mode = this.properties.getMode();
|
||||
if (mode == null) {
|
||||
mode = deduceMode();
|
||||
}
|
||||
if (mode == ArtemisMode.EMBEDDED) {
|
||||
return createEmbeddedConnectionFactory(factoryClass);
|
||||
}
|
||||
return createNativeConnectionFactory(factoryClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduce the {@link ArtemisMode} to use if none has been set.
|
||||
* @return the mode
|
||||
*/
|
||||
private ArtemisMode deduceMode() {
|
||||
if (this.properties.getEmbedded().isEnabled() && isEmbeddedJmsClassPresent()) {
|
||||
return ArtemisMode.EMBEDDED;
|
||||
}
|
||||
return ArtemisMode.NATIVE;
|
||||
}
|
||||
|
||||
private boolean isEmbeddedJmsClassPresent() {
|
||||
for (String embeddedJmsClass : EMBEDDED_JMS_CLASSES) {
|
||||
if (ClassUtils.isPresent(embeddedJmsClass, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private <T extends ActiveMQConnectionFactory> T createEmbeddedConnectionFactory(Class<T> factoryClass)
|
||||
throws Exception {
|
||||
try {
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration(
|
||||
InVMConnectorFactory.class.getName(), this.properties.getEmbedded().generateTransportParameters());
|
||||
ServerLocator serviceLocator = ActiveMQClient.createServerLocatorWithoutHA(transportConfiguration);
|
||||
return factoryClass.getConstructor(ServerLocator.class).newInstance(serviceLocator);
|
||||
}
|
||||
catch (NoClassDefFoundError ex) {
|
||||
throw new IllegalStateException("Unable to create InVM "
|
||||
+ "Artemis connection, ensure that artemis-jms-server.jar is in the classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends ActiveMQConnectionFactory> T createNativeConnectionFactory(Class<T> factoryClass)
|
||||
throws Exception {
|
||||
T connectionFactory = newNativeConnectionFactory(factoryClass);
|
||||
String user = this.properties.getUser();
|
||||
if (StringUtils.hasText(user)) {
|
||||
connectionFactory.setUser(user);
|
||||
connectionFactory.setPassword(this.properties.getPassword());
|
||||
}
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private <T extends ActiveMQConnectionFactory> T newNativeConnectionFactory(Class<T> factoryClass) throws Exception {
|
||||
// Fallback if the broker url is not set
|
||||
if (!StringUtils.hasText(this.properties.getBrokerUrl()) && StringUtils.hasText(this.properties.getHost())) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.HOST_PROP_NAME, this.properties.getHost());
|
||||
params.put(TransportConstants.PORT_PROP_NAME, this.properties.getPort());
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration(
|
||||
NettyConnectorFactory.class.getName(), params);
|
||||
Constructor<T> constructor = factoryClass.getConstructor(boolean.class, TransportConfiguration[].class);
|
||||
return constructor.newInstance(false, new TransportConfiguration[] { transportConfiguration });
|
||||
}
|
||||
String brokerUrl = StringUtils.hasText(this.properties.getBrokerUrl()) ? this.properties.getBrokerUrl()
|
||||
: DEFAULT_BROKER_URL;
|
||||
Constructor<T> constructor = factoryClass.getConstructor(String.class);
|
||||
return constructor.newInstance(brokerUrl);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.QueueConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.server.JournalType;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Configuration used to create the embedded Artemis server.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ArtemisEmbeddedConfigurationFactory {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ArtemisEmbeddedConfigurationFactory.class);
|
||||
|
||||
private final ArtemisProperties.Embedded properties;
|
||||
|
||||
ArtemisEmbeddedConfigurationFactory(ArtemisProperties properties) {
|
||||
this.properties = properties.getEmbedded();
|
||||
}
|
||||
|
||||
Configuration createConfiguration() {
|
||||
ConfigurationImpl configuration = new ConfigurationImpl();
|
||||
configuration.setSecurityEnabled(false);
|
||||
configuration.setPersistenceEnabled(this.properties.isPersistent());
|
||||
String dataDir = getDataDir();
|
||||
configuration.setJournalDirectory(dataDir + "/journal");
|
||||
if (this.properties.isPersistent()) {
|
||||
configuration.setJournalType(JournalType.NIO);
|
||||
configuration.setLargeMessagesDirectory(dataDir + "/largemessages");
|
||||
configuration.setBindingsDirectory(dataDir + "/bindings");
|
||||
configuration.setPagingDirectory(dataDir + "/paging");
|
||||
}
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration(InVMAcceptorFactory.class.getName(),
|
||||
this.properties.generateTransportParameters());
|
||||
configuration.getAcceptorConfigurations().add(transportConfiguration);
|
||||
if (this.properties.isDefaultClusterPassword() && logger.isDebugEnabled()) {
|
||||
logger.debug("Using default Artemis cluster password: " + this.properties.getClusterPassword());
|
||||
}
|
||||
configuration.setClusterPassword(this.properties.getClusterPassword());
|
||||
configuration.addAddressConfiguration(createAddressConfiguration("DLQ"));
|
||||
configuration.addAddressConfiguration(createAddressConfiguration("ExpiryQueue"));
|
||||
configuration.addAddressesSetting("#",
|
||||
new AddressSettings().setDeadLetterAddress(SimpleString.toSimpleString("DLQ"))
|
||||
.setExpiryAddress(SimpleString.toSimpleString("ExpiryQueue")));
|
||||
return configuration;
|
||||
}
|
||||
|
||||
private CoreAddressConfiguration createAddressConfiguration(String name) {
|
||||
return new CoreAddressConfiguration().setName(name).addRoutingType(RoutingType.ANYCAST).addQueueConfiguration(
|
||||
new QueueConfiguration(name).setRoutingType(RoutingType.ANYCAST).setAddress(name));
|
||||
}
|
||||
|
||||
private String getDataDir() {
|
||||
if (this.properties.getDataDirectory() != null) {
|
||||
return this.properties.getDataDirectory();
|
||||
}
|
||||
String tempDirectory = System.getProperty("java.io.tmpdir");
|
||||
return new File(tempDirectory, "artemis-data").getAbsolutePath();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.QueueConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
|
||||
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
|
||||
import org.apache.activemq.artemis.jms.server.config.JMSConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.TopicConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl;
|
||||
|
||||
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.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Configuration used to create the embedded Artemis server.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(EmbeddedActiveMQ.class)
|
||||
@ConditionalOnProperty(prefix = "spring.artemis.embedded", name = "enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
class ArtemisEmbeddedServerConfiguration {
|
||||
|
||||
private final ArtemisProperties properties;
|
||||
|
||||
ArtemisEmbeddedServerConfiguration(ArtemisProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
org.apache.activemq.artemis.core.config.Configuration artemisConfiguration() {
|
||||
return new ArtemisEmbeddedConfigurationFactory(this.properties).createConfiguration();
|
||||
}
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "stop")
|
||||
@ConditionalOnMissingBean
|
||||
EmbeddedActiveMQ embeddedActiveMq(org.apache.activemq.artemis.core.config.Configuration configuration,
|
||||
JMSConfiguration jmsConfiguration, ObjectProvider<ArtemisConfigurationCustomizer> configurationCustomizers)
|
||||
throws Exception {
|
||||
for (JMSQueueConfiguration queueConfiguration : jmsConfiguration.getQueueConfigurations()) {
|
||||
String queueName = queueConfiguration.getName();
|
||||
configuration.addAddressConfiguration(
|
||||
new CoreAddressConfiguration().setName(queueName).addRoutingType(RoutingType.ANYCAST)
|
||||
.addQueueConfiguration(new QueueConfiguration(queueName).setAddress(queueName)
|
||||
.setFilterString(queueConfiguration.getSelector())
|
||||
.setDurable(queueConfiguration.isDurable()).setRoutingType(RoutingType.ANYCAST)));
|
||||
}
|
||||
for (TopicConfiguration topicConfiguration : jmsConfiguration.getTopicConfigurations()) {
|
||||
configuration.addAddressConfiguration(new CoreAddressConfiguration().setName(topicConfiguration.getName())
|
||||
.addRoutingType(RoutingType.MULTICAST));
|
||||
}
|
||||
configurationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(configuration));
|
||||
EmbeddedActiveMQ embeddedActiveMq = new EmbeddedActiveMQ();
|
||||
embeddedActiveMq.setConfiguration(configuration);
|
||||
return embeddedActiveMq;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
JMSConfiguration artemisJmsConfiguration(ObjectProvider<JMSQueueConfiguration> queuesConfiguration,
|
||||
ObjectProvider<TopicConfiguration> topicsConfiguration) {
|
||||
JMSConfiguration configuration = new JMSConfigurationImpl();
|
||||
addAll(configuration.getQueueConfigurations(), queuesConfiguration);
|
||||
addAll(configuration.getTopicConfigurations(), topicsConfiguration);
|
||||
addQueues(configuration, this.properties.getEmbedded().getQueues());
|
||||
addTopics(configuration, this.properties.getEmbedded().getTopics());
|
||||
return configuration;
|
||||
}
|
||||
|
||||
private <T> void addAll(List<T> list, ObjectProvider<T> items) {
|
||||
if (items != null) {
|
||||
list.addAll(items.orderedStream().collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
private void addQueues(JMSConfiguration configuration, String[] queues) {
|
||||
boolean persistent = this.properties.getEmbedded().isPersistent();
|
||||
for (String queue : queues) {
|
||||
JMSQueueConfigurationImpl jmsQueueConfiguration = new JMSQueueConfigurationImpl();
|
||||
jmsQueueConfiguration.setName(queue);
|
||||
jmsQueueConfiguration.setDurable(persistent);
|
||||
jmsQueueConfiguration.setBindings("/queue/" + queue);
|
||||
configuration.getQueueConfigurations().add(jmsQueueConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
private void addTopics(JMSConfiguration configuration, String[] topics) {
|
||||
for (String topic : topics) {
|
||||
TopicConfigurationImpl topicConfiguration = new TopicConfigurationImpl();
|
||||
topicConfiguration.setName(topic);
|
||||
topicConfiguration.setBindings("/topic/" + topic);
|
||||
configuration.getTopicConfigurations().add(topicConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
/**
|
||||
* Define the mode in which Artemis can operate.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public enum ArtemisMode {
|
||||
|
||||
/**
|
||||
* Connect to a broker using the native Artemis protocol (i.e. netty).
|
||||
*/
|
||||
NATIVE,
|
||||
|
||||
/**
|
||||
* Embed (i.e. start) the broker in the application.
|
||||
*/
|
||||
EMBEDDED
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import org.apache.activemq.artemis.spi.core.naming.BindingRegistry;
|
||||
|
||||
/**
|
||||
* A no-op implementation of the {@link BindingRegistry}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class ArtemisNoOpBindingRegistry implements BindingRegistry {
|
||||
|
||||
@Override
|
||||
public Object lookup(String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bind(String s, Object o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(String s) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.jms.artemis;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jms.JmsPoolConnectionFactoryProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
|
||||
/**
|
||||
* Configuration properties for Artemis.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Justin Bertram
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.artemis")
|
||||
public class ArtemisProperties {
|
||||
|
||||
/**
|
||||
* Artemis deployment mode, auto-detected by default.
|
||||
*/
|
||||
private ArtemisMode mode;
|
||||
|
||||
/**
|
||||
* Artemis broker port.
|
||||
*/
|
||||
private String brokerUrl;
|
||||
|
||||
/**
|
||||
* Artemis broker host.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* Artemis broker port.
|
||||
*/
|
||||
private int port = 61616;
|
||||
|
||||
/**
|
||||
* Login user of the broker.
|
||||
*/
|
||||
private String user;
|
||||
|
||||
/**
|
||||
* Login password of the broker.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
private final Embedded embedded = new Embedded();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final JmsPoolConnectionFactoryProperties pool = new JmsPoolConnectionFactoryProperties();
|
||||
|
||||
public ArtemisMode getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
public void setMode(ArtemisMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getBrokerUrl() {
|
||||
return this.brokerUrl;
|
||||
}
|
||||
|
||||
public void setBrokerUrl(String brokerUrl) {
|
||||
this.brokerUrl = brokerUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the host of the broker.
|
||||
* @return the host
|
||||
* @deprecated since 2.5.0 for removal in 2.7.0 in favor of broker url
|
||||
*/
|
||||
@Deprecated
|
||||
@DeprecatedConfigurationProperty(replacement = "spring.artemis.broker-url")
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the port of the broker.
|
||||
* @return the port
|
||||
* @deprecated since 2.5.0 for removal in 2.7.0 in favor of broker url
|
||||
*/
|
||||
@Deprecated
|
||||
@DeprecatedConfigurationProperty(replacement = "spring.artemis.broker-url")
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
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 Embedded getEmbedded() {
|
||||
return this.embedded;
|
||||
}
|
||||
|
||||
public JmsPoolConnectionFactoryProperties getPool() {
|
||||
return this.pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for an embedded Artemis server.
|
||||
*/
|
||||
public static class Embedded {
|
||||
|
||||
private static final AtomicInteger serverIdCounter = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Server ID. By default, an auto-incremented counter is used.
|
||||
*/
|
||||
private int serverId = serverIdCounter.getAndIncrement();
|
||||
|
||||
/**
|
||||
* Whether to enable embedded mode if the Artemis server APIs are available.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Whether to enable persistent store.
|
||||
*/
|
||||
private boolean persistent;
|
||||
|
||||
/**
|
||||
* Journal file directory. Not necessary if persistence is turned off.
|
||||
*/
|
||||
private String dataDirectory;
|
||||
|
||||
/**
|
||||
* Comma-separated list of queues to create on startup.
|
||||
*/
|
||||
private String[] queues = new String[0];
|
||||
|
||||
/**
|
||||
* Comma-separated list of topics to create on startup.
|
||||
*/
|
||||
private String[] topics = new String[0];
|
||||
|
||||
/**
|
||||
* Cluster password. Randomly generated on startup by default.
|
||||
*/
|
||||
private String clusterPassword = UUID.randomUUID().toString();
|
||||
|
||||
private boolean defaultClusterPassword = true;
|
||||
|
||||
public int getServerId() {
|
||||
return this.serverId;
|
||||
}
|
||||
|
||||
public void setServerId(int serverId) {
|
||||
this.serverId = serverId;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return this.persistent;
|
||||
}
|
||||
|
||||
public void setPersistent(boolean persistent) {
|
||||
this.persistent = persistent;
|
||||
}
|
||||
|
||||
public String getDataDirectory() {
|
||||
return this.dataDirectory;
|
||||
}
|
||||
|
||||
public void setDataDirectory(String dataDirectory) {
|
||||
this.dataDirectory = dataDirectory;
|
||||
}
|
||||
|
||||
public String[] getQueues() {
|
||||
return this.queues;
|
||||
}
|
||||
|
||||
public void setQueues(String[] queues) {
|
||||
this.queues = queues;
|
||||
}
|
||||
|
||||
public String[] getTopics() {
|
||||
return this.topics;
|
||||
}
|
||||
|
||||
public void setTopics(String[] topics) {
|
||||
this.topics = topics;
|
||||
}
|
||||
|
||||
public String getClusterPassword() {
|
||||
return this.clusterPassword;
|
||||
}
|
||||
|
||||
public void setClusterPassword(String clusterPassword) {
|
||||
this.clusterPassword = clusterPassword;
|
||||
this.defaultClusterPassword = false;
|
||||
}
|
||||
|
||||
public boolean isDefaultClusterPassword() {
|
||||
return this.defaultClusterPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the minimal transport parameters for an embedded transport
|
||||
* configuration.
|
||||
* @return the transport parameters
|
||||
* @see TransportConstants#SERVER_ID_PROP_NAME
|
||||
*/
|
||||
public Map<String, Object> generateTransportParameters() {
|
||||
Map<String, Object> parameters = new HashMap<>();
|
||||
parameters.put(TransportConstants.SERVER_ID_PROP_NAME, getServerId());
|
||||
return parameters;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
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.jms.XAConnectionFactoryWrapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
/**
|
||||
* Configuration for Artemis XA {@link ConnectionFactory}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||
@ConditionalOnClass(TransactionManager.class)
|
||||
@ConditionalOnBean(XAConnectionFactoryWrapper.class)
|
||||
class ArtemisXAConnectionFactoryConfiguration {
|
||||
|
||||
@Primary
|
||||
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
|
||||
ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, ArtemisProperties properties,
|
||||
XAConnectionFactoryWrapper wrapper) throws Exception {
|
||||
return wrapper.wrapConnectionFactory(new ArtemisConnectionFactoryFactory(beanFactory, properties)
|
||||
.createConnectionFactory(ActiveMQXAConnectionFactory.class));
|
||||
}
|
||||
|
||||
@Bean
|
||||
ActiveMQXAConnectionFactory nonXaJmsConnectionFactory(ListableBeanFactory beanFactory,
|
||||
ArtemisProperties properties) {
|
||||
return new ArtemisConnectionFactoryFactory(beanFactory, properties)
|
||||
.createConnectionFactory(ActiveMQXAConnectionFactory.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 Artemis.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.jms.artemis;
|
||||
|
|
@ -21,6 +21,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
|
@ -36,7 +37,8 @@ import org.springframework.context.annotation.Import;
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(jakarta.transaction.Transaction.class)
|
||||
@ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true)
|
||||
@AutoConfigureBefore({ XADataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
||||
@AutoConfigureBefore({ XADataSourceAutoConfiguration.class, ArtemisAutoConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class })
|
||||
@Import(JndiJtaConfiguration.class)
|
||||
public class JtaAutoConfiguration {
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConf
|
|||
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@ import jakarta.jms.ConnectionFactory;
|
|||
import jakarta.jms.ExceptionListener;
|
||||
import jakarta.jms.Session;
|
||||
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -38,6 +40,7 @@ import org.springframework.jms.config.JmsListenerConfigUtils;
|
|||
import org.springframework.jms.config.JmsListenerContainerFactory;
|
||||
import org.springframework.jms.config.JmsListenerEndpoint;
|
||||
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
|
||||
import org.springframework.jms.connection.CachingConnectionFactory;
|
||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.listener.DefaultMessageListenerContainer;
|
||||
|
|
@ -59,8 +62,32 @@ import static org.mockito.Mockito.mock;
|
|||
class JmsAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JmsAutoConfiguration.class))
|
||||
.withUserConfiguration(ConnectionFactoryConfiguration.class);
|
||||
.withConfiguration(AutoConfigurations.of(ArtemisAutoConfiguration.class, JmsAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void testDefaultJmsConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).run(this::testDefaultJmsConfiguration);
|
||||
}
|
||||
|
||||
private void testDefaultJmsConfiguration(AssertableApplicationContext loaded) {
|
||||
assertThat(loaded).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(loaded).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory factory = loaded.getBean(CachingConnectionFactory.class);
|
||||
assertThat(factory.getTargetConnectionFactory()).isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
JmsTemplate jmsTemplate = loaded.getBean(JmsTemplate.class);
|
||||
JmsMessagingTemplate messagingTemplate = loaded.getBean(JmsMessagingTemplate.class);
|
||||
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate);
|
||||
assertThat(getBrokerUrl(factory)).startsWith("vm://");
|
||||
assertThat(loaded.containsBean("jmsListenerContainerFactory")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConnectionFactoryBackOff() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration2.class)
|
||||
.run((context) -> assertThat(context.getBeansOfType(ActiveMQConnectionFactory.class))
|
||||
.containsOnlyKeys("customConnectionFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJmsTemplateBackOff() {
|
||||
|
|
@ -77,13 +104,15 @@ class JmsAutoConfigurationTests {
|
|||
|
||||
@Test
|
||||
void testJmsTemplateBackOffEverything() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration3.class, TestConfiguration5.class)
|
||||
this.contextRunner
|
||||
.withUserConfiguration(TestConfiguration2.class, TestConfiguration3.class, TestConfiguration5.class)
|
||||
.run(this::testJmsTemplateBackOffEverything);
|
||||
}
|
||||
|
||||
private void testJmsTemplateBackOffEverything(AssertableApplicationContext loaded) throws IOException {
|
||||
JmsTemplate jmsTemplate = loaded.getBean(JmsTemplate.class);
|
||||
assertThat(jmsTemplate.getPriority()).isEqualTo(999);
|
||||
assertThat(loaded.getBeansOfType(ActiveMQConnectionFactory.class)).containsOnlyKeys("customConnectionFactory");
|
||||
JmsMessagingTemplate messagingTemplate = loaded.getBean(JmsMessagingTemplate.class);
|
||||
assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar");
|
||||
assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate);
|
||||
|
|
@ -288,6 +317,16 @@ class JmsAutoConfigurationTests {
|
|||
});
|
||||
}
|
||||
|
||||
private String getBrokerUrl(CachingConnectionFactory connectionFactory) {
|
||||
assertThat(connectionFactory.getTargetConnectionFactory()).isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
try {
|
||||
return ((ActiveMQConnectionFactory) connectionFactory.getTargetConnectionFactory()).toURI().toString();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void enableJmsAutomatically() {
|
||||
this.contextRunner.withUserConfiguration(NoEnableJmsConfiguration.class)
|
||||
|
|
@ -297,17 +336,17 @@ class JmsAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ConnectionFactoryConfiguration {
|
||||
|
||||
@Bean
|
||||
ConnectionFactory connectionFactory() {
|
||||
return mock(ConnectionFactory.class);
|
||||
}
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TestConfiguration {
|
||||
static class TestConfiguration2 {
|
||||
|
||||
@Bean
|
||||
ConnectionFactory customConnectionFactory() {
|
||||
return new ActiveMQConnectionFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -437,12 +476,12 @@ class JmsAutoConfigurationTests {
|
|||
|
||||
@Bean
|
||||
ConnectionFactory connectionFactory1() {
|
||||
return mock(ConnectionFactory.class);
|
||||
return new ActiveMQConnectionFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ConnectionFactory connectionFactory2() {
|
||||
return mock(ConnectionFactory.class);
|
||||
return new ActiveMQConnectionFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.BindingQueryResult;
|
||||
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.artemis.jms.server.config.JMSConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.TopicConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
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.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jms.connection.CachingConnectionFactory;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ArtemisAutoConfiguration}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class ArtemisAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ArtemisAutoConfiguration.class, JmsAutoConfiguration.class));
|
||||
|
||||
@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).doesNotHaveBean(CachingConnectionFactory.class);
|
||||
ConnectionFactory connectionFactory = getConnectionFactory(context);
|
||||
assertThat(connectionFactory).isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void nativeConnectionFactory() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:native").run((context) -> {
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ConnectionFactory connectionFactory = getConnectionFactory(context);
|
||||
assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
ActiveMQConnectionFactory activeMQConnectionFactory = getActiveMQConnectionFactory(
|
||||
connectionFactory);
|
||||
assertNettyConnectionFactory(activeMQConnectionFactory, "localhost", 61616);
|
||||
assertThat(activeMQConnectionFactory.getUser()).isNull();
|
||||
assertThat(activeMQConnectionFactory.getPassword()).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void nativeConnectionFactoryCustomBrokerUrl() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:native", "spring.artemis.broker-url:tcp://192.168.1.144:9876")
|
||||
.run((context) -> assertNettyConnectionFactory(
|
||||
getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void nativeConnectionFactoryCustomHost() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:native", "spring.artemis.host:192.168.1.144",
|
||||
"spring.artemis.port:9876")
|
||||
.run((context) -> assertNettyConnectionFactory(
|
||||
getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void nativeConnectionFactoryCustomBrokerUrlAndHost() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:native", "spring.artemis.host:192.168.1.144",
|
||||
"spring.artemis.port:9876", "spring.artemis.broker-url=tcp://192.168.1.221:6543")
|
||||
.run((context) -> assertNettyConnectionFactory(
|
||||
getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.221", 6543));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nativeConnectionFactoryCredentials() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:native", "spring.artemis.user:user",
|
||||
"spring.artemis.password:secret")
|
||||
.run((context) -> {
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ConnectionFactory connectionFactory = getConnectionFactory(context);
|
||||
assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
ActiveMQConnectionFactory activeMQConnectionFactory = getActiveMQConnectionFactory(
|
||||
connectionFactory);
|
||||
assertNettyConnectionFactory(activeMQConnectionFactory, "localhost", 61616);
|
||||
assertThat(activeMQConnectionFactory.getUser()).isEqualTo("user");
|
||||
assertThat(activeMQConnectionFactory.getPassword()).isEqualTo("secret");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedConnectionFactory() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:embedded").run((context) -> {
|
||||
ArtemisProperties properties = context.getBean(ArtemisProperties.class);
|
||||
assertThat(properties.getMode()).isEqualTo(ArtemisMode.EMBEDDED);
|
||||
assertThat(context).hasSingleBean(EmbeddedActiveMQ.class);
|
||||
org.apache.activemq.artemis.core.config.Configuration configuration = context
|
||||
.getBean(org.apache.activemq.artemis.core.config.Configuration.class);
|
||||
assertThat(configuration.isPersistenceEnabled()).isFalse();
|
||||
assertThat(configuration.isSecurityEnabled()).isFalse();
|
||||
assertInVmConnectionFactory(getActiveMQConnectionFactory(getConnectionFactory(context)));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedConnectionFactoryByDefault() {
|
||||
// No mode is specified
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(EmbeddedActiveMQ.class);
|
||||
org.apache.activemq.artemis.core.config.Configuration configuration = context
|
||||
.getBean(org.apache.activemq.artemis.core.config.Configuration.class);
|
||||
assertThat(configuration.isPersistenceEnabled()).isFalse();
|
||||
assertThat(configuration.isSecurityEnabled()).isFalse();
|
||||
assertInVmConnectionFactory(getActiveMQConnectionFactory(getConnectionFactory(context)));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void nativeConnectionFactoryIfEmbeddedServiceDisabledExplicitly() {
|
||||
// No mode is specified
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.embedded.enabled:false").run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(ActiveMQServer.class);
|
||||
assertNettyConnectionFactory(getActiveMQConnectionFactory(getConnectionFactory(context)),
|
||||
"localhost", 61616);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedConnectionFactoryEvenIfEmbeddedServiceDisabled() {
|
||||
// No mode is specified
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:embedded", "spring.artemis.embedded.enabled:false")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(ActiveMQServer.class)).isEmpty();
|
||||
assertInVmConnectionFactory(getActiveMQConnectionFactory(getConnectionFactory(context)));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedServerWithDestinations() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.embedded.queues=Queue1,Queue2",
|
||||
"spring.artemis.embedded.topics=Topic1")
|
||||
.run((context) -> {
|
||||
DestinationChecker checker = new DestinationChecker(context);
|
||||
checker.checkQueue("Queue1", true);
|
||||
checker.checkQueue("Queue2", true);
|
||||
checker.checkQueue("NonExistentQueue", false);
|
||||
checker.checkTopic("Topic1", true);
|
||||
checker.checkTopic("NonExistentTopic", false);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedServerWithDestinationConfig() {
|
||||
this.contextRunner.withUserConfiguration(DestinationConfiguration.class).run((context) -> {
|
||||
DestinationChecker checker = new DestinationChecker(context);
|
||||
checker.checkQueue("sampleQueue", true);
|
||||
checker.checkTopic("sampleTopic", true);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedServiceWithCustomJmsConfiguration() {
|
||||
// Ignored with custom config
|
||||
this.contextRunner.withUserConfiguration(CustomJmsConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.embedded.queues=Queue1,Queue2").run((context) -> {
|
||||
DestinationChecker checker = new DestinationChecker(context);
|
||||
checker.checkQueue("custom", true); // See CustomJmsConfiguration
|
||||
checker.checkQueue("Queue1", false);
|
||||
checker.checkQueue("Queue2", false);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedServiceWithCustomArtemisConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(CustomArtemisConfiguration.class)
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(org.apache.activemq.artemis.core.config.Configuration.class).getName())
|
||||
.isEqualTo("customFooBar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedWithPersistentMode(@TempDir Path temp) throws IOException {
|
||||
File dataDirectory = Files.createTempDirectory(temp, null).toFile();
|
||||
final String messageId = UUID.randomUUID().toString();
|
||||
// Start the server and post a message to some queue
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.embedded.queues=TestQueue",
|
||||
"spring.artemis.embedded.persistent:true",
|
||||
"spring.artemis.embedded.dataDirectory:" + dataDirectory.getAbsolutePath())
|
||||
.run((context) -> context.getBean(JmsTemplate.class).send("TestQueue",
|
||||
(session) -> session.createTextMessage(messageId)))
|
||||
.run((context) -> {
|
||||
// Start the server again and check if our message is still here
|
||||
JmsTemplate jmsTemplate2 = context.getBean(JmsTemplate.class);
|
||||
jmsTemplate2.setReceiveTimeout(1000L);
|
||||
Message message = jmsTemplate2.receive("TestQueue");
|
||||
assertThat(message).isNotNull();
|
||||
assertThat(((TextMessage) message).getText()).isEqualTo(messageId);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void severalEmbeddedBrokers() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.embedded.queues=Queue1").run((first) -> {
|
||||
this.contextRunner.withPropertyValues("spring.artemis.embedded.queues=Queue2").run((second) -> {
|
||||
ArtemisProperties firstProperties = first.getBean(ArtemisProperties.class);
|
||||
ArtemisProperties secondProperties = second.getBean(ArtemisProperties.class);
|
||||
assertThat(firstProperties.getEmbedded().getServerId())
|
||||
.isLessThan(secondProperties.getEmbedded().getServerId());
|
||||
DestinationChecker firstChecker = new DestinationChecker(first);
|
||||
firstChecker.checkQueue("Queue1", true);
|
||||
firstChecker.checkQueue("Queue2", false);
|
||||
DestinationChecker secondChecker = new DestinationChecker(second);
|
||||
secondChecker.checkQueue("Queue1", false);
|
||||
secondChecker.checkQueue("Queue2", true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void connectToASpecificEmbeddedBroker() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.embedded.serverId=93", "spring.artemis.embedded.queues=Queue1")
|
||||
.run((first) -> {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode=embedded",
|
||||
// Connect to the "main" broker
|
||||
"spring.artemis.embedded.serverId=93",
|
||||
// Do not start a specific one
|
||||
"spring.artemis.embedded.enabled=false")
|
||||
.run((secondContext) -> {
|
||||
first.getBean(JmsTemplate.class).convertAndSend("Queue1", "test");
|
||||
assertThat(secondContext.getBean(JmsTemplate.class).receiveAndConvert("Queue1"))
|
||||
.isEqualTo("test");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultPoolConnectionFactoryIsApplied() {
|
||||
this.contextRunner.withPropertyValues("spring.artemis.pool.enabled=true").run((context) -> {
|
||||
assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class)).hasSize(1);
|
||||
JmsPoolConnectionFactory connectionFactory = context.getBean(JmsPoolConnectionFactory.class);
|
||||
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
|
||||
.withPropertyValues("spring.artemis.pool.enabled=true", "spring.artemis.pool.blockIfFull=false",
|
||||
"spring.artemis.pool.blockIfFullTimeout=64", "spring.artemis.pool.idleTimeout=512",
|
||||
"spring.artemis.pool.maxConnections=256", "spring.artemis.pool.maxSessionsPerConnection=1024",
|
||||
"spring.artemis.pool.timeBetweenExpirationCheck=2048",
|
||||
"spring.artemis.pool.useAnonymousProducers=false")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class)).hasSize(1);
|
||||
JmsPoolConnectionFactory connectionFactory = context.getBean(JmsPoolConnectionFactory.class);
|
||||
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.withPropertyValues("spring.artemis.pool.enabled:true").run((context) -> {
|
||||
ConnectionFactory factory = getConnectionFactory(context);
|
||||
assertThat(factory).isInstanceOf(JmsPoolConnectionFactory.class);
|
||||
context.getSourceApplicationContext().close();
|
||||
assertThat(factory.createConnection()).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
private ConnectionFactory getConnectionFactory(AssertableApplicationContext context) {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class).hasBean("jmsConnectionFactory");
|
||||
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class);
|
||||
assertThat(connectionFactory).isSameAs(context.getBean("jmsConnectionFactory"));
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
private ActiveMQConnectionFactory getActiveMQConnectionFactory(ConnectionFactory connectionFactory) {
|
||||
assertThat(connectionFactory).isInstanceOf(CachingConnectionFactory.class);
|
||||
return (ActiveMQConnectionFactory) ((CachingConnectionFactory) connectionFactory).getTargetConnectionFactory();
|
||||
}
|
||||
|
||||
private TransportConfiguration assertInVmConnectionFactory(ActiveMQConnectionFactory connectionFactory) {
|
||||
TransportConfiguration transportConfig = getSingleTransportConfiguration(connectionFactory);
|
||||
assertThat(transportConfig.getFactoryClassName()).isEqualTo(InVMConnectorFactory.class.getName());
|
||||
return transportConfig;
|
||||
}
|
||||
|
||||
private TransportConfiguration assertNettyConnectionFactory(ActiveMQConnectionFactory connectionFactory,
|
||||
String host, int port) {
|
||||
TransportConfiguration transportConfig = getSingleTransportConfiguration(connectionFactory);
|
||||
assertThat(transportConfig.getFactoryClassName()).isEqualTo(NettyConnectorFactory.class.getName());
|
||||
assertThat(transportConfig.getParams().get("host")).isEqualTo(host);
|
||||
Object transportConfigPort = transportConfig.getParams().get("port");
|
||||
if (transportConfigPort instanceof String) {
|
||||
transportConfigPort = Integer.parseInt((String) transportConfigPort);
|
||||
}
|
||||
assertThat(transportConfigPort).isEqualTo(port);
|
||||
return transportConfig;
|
||||
}
|
||||
|
||||
private TransportConfiguration getSingleTransportConfiguration(ActiveMQConnectionFactory connectionFactory) {
|
||||
TransportConfiguration[] transportConfigurations = connectionFactory.getServerLocator()
|
||||
.getStaticTransportConfigurations();
|
||||
assertThat(transportConfigurations).hasSize(1);
|
||||
return transportConfigurations[0];
|
||||
}
|
||||
|
||||
private static final class DestinationChecker {
|
||||
|
||||
private final ActiveMQServer server;
|
||||
|
||||
private DestinationChecker(ApplicationContext applicationContext) {
|
||||
this.server = applicationContext.getBean(EmbeddedActiveMQ.class).getActiveMQServer();
|
||||
}
|
||||
|
||||
void checkQueue(String name, boolean shouldExist) {
|
||||
checkDestination(name, RoutingType.ANYCAST, shouldExist);
|
||||
}
|
||||
|
||||
void checkTopic(String name, boolean shouldExist) {
|
||||
checkDestination(name, RoutingType.MULTICAST, shouldExist);
|
||||
}
|
||||
|
||||
void checkDestination(String name, RoutingType routingType, boolean shouldExist) {
|
||||
try {
|
||||
BindingQueryResult result = this.server.bindingQuery(new SimpleString(name));
|
||||
assertThat(result.isExists()).isEqualTo(shouldExist);
|
||||
if (shouldExist) {
|
||||
assertThat(result.getAddressInfo().getRoutingType()).isEqualTo(routingType);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class DestinationConfiguration {
|
||||
|
||||
@Bean
|
||||
JMSQueueConfiguration sampleQueueConfiguration() {
|
||||
JMSQueueConfigurationImpl jmsQueueConfiguration = new JMSQueueConfigurationImpl();
|
||||
jmsQueueConfiguration.setName("sampleQueue");
|
||||
jmsQueueConfiguration.setSelector("foo=bar");
|
||||
jmsQueueConfiguration.setDurable(false);
|
||||
jmsQueueConfiguration.setBindings("/queue/1");
|
||||
return jmsQueueConfiguration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
TopicConfiguration sampleTopicConfiguration() {
|
||||
TopicConfigurationImpl topicConfiguration = new TopicConfigurationImpl();
|
||||
topicConfiguration.setName("sampleTopic");
|
||||
topicConfiguration.setBindings("/topic/1");
|
||||
return topicConfiguration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomJmsConfiguration {
|
||||
|
||||
@Bean
|
||||
JMSConfiguration myJmsConfiguration() {
|
||||
JMSConfiguration config = new JMSConfigurationImpl();
|
||||
JMSQueueConfiguration jmsQueueConfiguration = new JMSQueueConfigurationImpl();
|
||||
jmsQueueConfiguration.setName("custom");
|
||||
jmsQueueConfiguration.setDurable(false);
|
||||
config.getQueueConfigurations().add(jmsQueueConfiguration);
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomArtemisConfiguration {
|
||||
|
||||
@Bean
|
||||
ArtemisConfigurationCustomizer myArtemisCustomize() {
|
||||
return (configuration) -> {
|
||||
configuration.setClusterPassword("Foobar");
|
||||
configuration.setName("customFooBar");
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.artemis;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
|
||||
import org.apache.activemq.artemis.core.server.JournalType;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ArtemisEmbeddedConfigurationFactory}
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ArtemisEmbeddedConfigurationFactoryTests {
|
||||
|
||||
@Test
|
||||
void defaultDataDir() {
|
||||
ArtemisProperties properties = new ArtemisProperties();
|
||||
properties.getEmbedded().setPersistent(true);
|
||||
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties).createConfiguration();
|
||||
assertThat(configuration.getJournalDirectory()).startsWith(System.getProperty("java.io.tmpdir"))
|
||||
.endsWith("/journal");
|
||||
}
|
||||
|
||||
@Test
|
||||
void persistenceSetup() {
|
||||
ArtemisProperties properties = new ArtemisProperties();
|
||||
properties.getEmbedded().setPersistent(true);
|
||||
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties).createConfiguration();
|
||||
assertThat(configuration.isPersistenceEnabled()).isTrue();
|
||||
assertThat(configuration.getJournalType()).isEqualTo(JournalType.NIO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void generatedClusterPassword() {
|
||||
ArtemisProperties properties = new ArtemisProperties();
|
||||
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties).createConfiguration();
|
||||
assertThat(configuration.getClusterPassword()).hasSize(36);
|
||||
}
|
||||
|
||||
@Test
|
||||
void specificClusterPassword() {
|
||||
ArtemisProperties properties = new ArtemisProperties();
|
||||
properties.getEmbedded().setClusterPassword("password");
|
||||
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties).createConfiguration();
|
||||
assertThat(configuration.getClusterPassword()).isEqualTo("password");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasDlqExpiryQueueAddressSettingsConfigured() {
|
||||
ArtemisProperties properties = new ArtemisProperties();
|
||||
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties).createConfiguration();
|
||||
Map<String, AddressSettings> addressesSettings = configuration.getAddressesSettings();
|
||||
assertThat((Object) addressesSettings.get("#").getDeadLetterAddress())
|
||||
.isEqualTo(SimpleString.toSimpleString("DLQ"));
|
||||
assertThat((Object) addressesSettings.get("#").getExpiryAddress())
|
||||
.isEqualTo(SimpleString.toSimpleString("ExpiryQueue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasDlqExpiryQueueConfigured() {
|
||||
ArtemisProperties properties = new ArtemisProperties();
|
||||
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties).createConfiguration();
|
||||
List<CoreAddressConfiguration> addressConfigurations = configuration.getAddressConfigurations();
|
||||
assertThat(addressConfigurations).hasSize(2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -73,6 +73,7 @@ dependencies {
|
|||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-actuator", configuration: "mavenRepository"))
|
||||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-amqp", configuration: "mavenRepository"))
|
||||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-aop", configuration: "mavenRepository"))
|
||||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-artemis", configuration: "mavenRepository"))
|
||||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-batch", configuration: "mavenRepository"))
|
||||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-data-jpa", configuration: "mavenRepository"))
|
||||
testRepository(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-jdbc", configuration: "mavenRepository"))
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ class SampleIntegrationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Requires Artemis to be run, so disable it")
|
||||
void jmsSample() throws Exception {
|
||||
System.setProperty("spring.artemis.embedded.queues", "spring-boot");
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,32 @@ bom {
|
|||
]
|
||||
}
|
||||
}
|
||||
library("Artemis", "2.19.0") {
|
||||
group("org.apache.activemq") {
|
||||
modules = [
|
||||
"artemis-amqp-protocol",
|
||||
"artemis-commons" {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
},
|
||||
"artemis-core-client" {
|
||||
exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec"
|
||||
},
|
||||
"artemis-jms-client" {
|
||||
exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec"
|
||||
},
|
||||
"artemis-jms-server" {
|
||||
exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec"
|
||||
},
|
||||
"artemis-journal",
|
||||
"artemis-selector",
|
||||
"artemis-server" {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec"
|
||||
},
|
||||
"artemis-service-extensions"
|
||||
]
|
||||
}
|
||||
}
|
||||
library("AspectJ", "1.9.7") {
|
||||
group("org.aspectj") {
|
||||
modules = [
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
== Messaging
|
||||
If your application uses any messaging protocol, see one or more of the following sections:
|
||||
|
||||
* *JMS:* <<messaging#messaging.jms, Auto-configuration for ActiveMQ, Sending and Receiving messages through JMS>>
|
||||
* *JMS:* <<messaging#messaging.jms, Auto-configuration for ActiveMQ and Artemis, Sending and Receiving messages through JMS>>
|
||||
* *AMQP:* <<messaging#messaging.amqp, Auto-configuration for RabbitMQ>>
|
||||
* *Kafka:* <<messaging#messaging.kafka, Auto-configuration for Spring Kafka>>
|
||||
* *RSocket:* <<messaging#messaging.rsocket, Auto-configuration for Spring Framework's RSocket Support>>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,59 @@ Spring Boot also auto-configures the necessary infrastructure to send and receiv
|
|||
|
||||
|
||||
|
||||
[[messaging.jms.artemis]]
|
||||
=== 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.
|
||||
If the broker is present, an embedded broker is automatically started and configured (unless the mode property has been explicitly set).
|
||||
The supported modes are `embedded` (to make explicit that an embedded broker is required and that an error should occur if the broker is not available on the classpath) and `native` (to connect to a broker using the `netty` transport protocol).
|
||||
When the latter is configured, Spring Boot configures a `ConnectionFactory` that connects to a broker running on the local machine with the default settings.
|
||||
|
||||
NOTE: If you use `spring-boot-starter-artemis`, the necessary dependencies to connect to an existing ActiveMQ Artemis instance are provided, as well as the Spring infrastructure to integrate with JMS.
|
||||
Adding `org.apache.activemq:artemis-jms-server` to your application lets you use embedded mode.
|
||||
|
||||
ActiveMQ Artemis configuration is controlled by external configuration properties in `+spring.artemis.*+`.
|
||||
For example, you might declare the following section in `application.properties`:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
----
|
||||
spring:
|
||||
artemis:
|
||||
mode: native
|
||||
broker-url: "tcp://192.168.1.210:9876"
|
||||
user: "admin"
|
||||
password: "secret"
|
||||
----
|
||||
|
||||
When embedding the broker, you can choose if you want to enable persistence and list the destinations that should be made available.
|
||||
These can be specified as a comma-separated list to create them with the default options, or you can define bean(s) of type `org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration` or `org.apache.activemq.artemis.jms.server.config.TopicConfiguration`, for advanced queue and topic configurations, respectively.
|
||||
|
||||
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:
|
||||
artemis:
|
||||
pool:
|
||||
enabled: true
|
||||
max-connections: 50
|
||||
----
|
||||
|
||||
See {spring-boot-autoconfigure-module-code}/jms/artemis/ArtemisProperties.java[`ArtemisProperties`] for more supported options.
|
||||
|
||||
No JNDI lookup is involved, and destinations are resolved against their names, using either the `name` attribute in the Artemis configuration or the names provided through configuration.
|
||||
|
||||
|
||||
|
||||
[[messaging.jms.jndi]]
|
||||
=== Using a JNDI ConnectionFactory
|
||||
If you are running your application in an application server, Spring Boot tries to locate a JMS `ConnectionFactory` by using JNDI.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id "org.springframework.boot.starter"
|
||||
}
|
||||
|
||||
description = "Starter for JMS messaging using Apache Artemis"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
|
||||
api("org.springframework:spring-jms")
|
||||
api("org.apache.activemq:artemis-jms-client") {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue