Merge pull request #3246 from eddumelendez/gh-3154
* gh-3154: Document Apache Artemis support Add Apache Artemis Starter POM Add Apache Artemis supportpull/3243/merge
commit
a0dde9f17d
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.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
|
||||||
|
* @since 1.3.0
|
||||||
|
* @see ArtemisProperties
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@AutoConfigureBefore(JmsAutoConfiguration.class)
|
||||||
|
@AutoConfigureAfter({ JndiConnectionFactoryAutoConfiguration.class })
|
||||||
|
@ConditionalOnClass({ ConnectionFactory.class, ActiveMQConnectionFactory.class })
|
||||||
|
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||||
|
@EnableConfigurationProperties(ArtemisProperties.class)
|
||||||
|
@Import({ ArtemisXAConnectionFactoryConfiguration.class,
|
||||||
|
ArtemisConnectionFactoryConfiguration.class })
|
||||||
|
public class ArtemisAutoConfiguration {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.jms.server.embedded.EmbeddedJMS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 EmbeddedJMS} instance.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 1.3.0
|
||||||
|
* @see ArtemisAutoConfiguration
|
||||||
|
*/
|
||||||
|
public interface ArtemisConfigurationCustomizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize the configuration.
|
||||||
|
* @param configuration the configuration to customize
|
||||||
|
*/
|
||||||
|
void customize(Configuration configuration);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.beans.factory.ListableBeanFactory;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for Artemis {@link ConnectionFactory}.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||||
|
class ArtemisConnectionFactoryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory,
|
||||||
|
ArtemisProperties properties) {
|
||||||
|
return new ArtemisConnectionFactoryFactory(beanFactory, properties)
|
||||||
|
.createConnectionFactory(ActiveMQConnectionFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to create a Artemis {@link ActiveMQConnectionFactory} instance from properties
|
||||||
|
* defined in {@link ArtemisProperties}.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class ArtemisConnectionFactoryFactory {
|
||||||
|
|
||||||
|
static final String EMBEDDED_JMS_CLASS = "org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ";
|
||||||
|
|
||||||
|
private final ArtemisProperties properties;
|
||||||
|
|
||||||
|
private final ListableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
public 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <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() {
|
||||||
|
if (ClassUtils.isPresent(EMBEDDED_JMS_CLASS, null)) {
|
||||||
|
try {
|
||||||
|
this.beanFactory.getBeansOfType(Class.forName(EMBEDDED_JMS_CLASS));
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
private ArtemisMode deduceMode() {
|
||||||
|
if (this.properties.getEmbedded().isEnabled()
|
||||||
|
&& ClassUtils.isPresent(EMBEDDED_JMS_CLASS, null)) {
|
||||||
|
return ArtemisMode.EMBEDDED;
|
||||||
|
}
|
||||||
|
return ArtemisMode.NATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.TransportConfiguration;
|
||||||
|
import org.apache.activemq.artemis.core.config.Configuration;
|
||||||
|
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.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration used to create the embedded Artemis server.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Stephane Nicol
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class ArtemisEmbeddedConfigurationFactory {
|
||||||
|
|
||||||
|
private Log logger = LogFactory.getLog(ArtemisEmbeddedConfigurationFactory.class);
|
||||||
|
|
||||||
|
private final ArtemisProperties.Embedded properties;
|
||||||
|
|
||||||
|
public ArtemisEmbeddedConfigurationFactory(ArtemisProperties properties) {
|
||||||
|
this.properties = properties.getEmbedded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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()) {
|
||||||
|
this.logger.debug("Using default Artemis cluster password: "
|
||||||
|
+ this.properties.getClusterPassword());
|
||||||
|
}
|
||||||
|
configuration.setClusterPassword(this.properties.getClusterPassword());
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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;
|
||||||
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration used to create the embedded Artemis server.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass(name = ArtemisConnectionFactoryFactory.EMBEDDED_JMS_CLASS)
|
||||||
|
@ConditionalOnProperty(prefix = "spring.artemis.embedded", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
class ArtemisEmbeddedServerConfiguration {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ArtemisProperties properties;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private List<ArtemisConfigurationCustomizer> configurationCustomizers;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private List<JMSQueueConfiguration> queuesConfiguration;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private List<TopicConfiguration> topicsConfiguration;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public org.apache.activemq.artemis.core.config.Configuration artemisConfiguration() {
|
||||||
|
return new ArtemisEmbeddedConfigurationFactory(this.properties)
|
||||||
|
.createConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(initMethod = "start", destroyMethod = "stop")
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public EmbeddedJMS artemisServer(
|
||||||
|
org.apache.activemq.artemis.core.config.Configuration configuration,
|
||||||
|
JMSConfiguration jmsConfiguration) {
|
||||||
|
EmbeddedJMS server = new EmbeddedJMS();
|
||||||
|
customize(configuration);
|
||||||
|
server.setConfiguration(configuration);
|
||||||
|
server.setJmsConfiguration(jmsConfiguration);
|
||||||
|
server.setRegistry(new ArtemisNoOpBindingRegistry());
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void customize(
|
||||||
|
org.apache.activemq.artemis.core.config.Configuration configuration) {
|
||||||
|
if (this.configurationCustomizers != null) {
|
||||||
|
AnnotationAwareOrderComparator.sort(this.configurationCustomizers);
|
||||||
|
for (ArtemisConfigurationCustomizer customizer : this.configurationCustomizers) {
|
||||||
|
customizer.customize(configuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public JMSConfiguration artemisJmsConfiguration() {
|
||||||
|
JMSConfiguration configuration = new JMSConfigurationImpl();
|
||||||
|
addAll(configuration.getQueueConfigurations(), this.queuesConfiguration);
|
||||||
|
addAll(configuration.getTopicConfigurations(), this.topicsConfiguration);
|
||||||
|
addQueues(configuration, this.properties.getEmbedded().getQueues());
|
||||||
|
addTopics(configuration, this.properties.getEmbedded().getTopics());
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void addAll(List<T> list, Collection<? extends T> items) {
|
||||||
|
if (items != null) {
|
||||||
|
list.addAll(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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-2015 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
|
||||||
|
*
|
||||||
|
* http://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-2015 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
|
||||||
|
*
|
||||||
|
* http://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,202 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration properties for Artemis
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix = "spring.artemis")
|
||||||
|
public class ArtemisProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Artemis deployment mode, auto-detected by default. Can be explicitly set to
|
||||||
|
* "native" or "embedded".
|
||||||
|
*/
|
||||||
|
private ArtemisMode mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Artemis broker host.
|
||||||
|
*/
|
||||||
|
private String host = "localhost";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Artemis broker port.
|
||||||
|
*/
|
||||||
|
private int port = 61616;
|
||||||
|
|
||||||
|
private final Embedded embedded = new Embedded();
|
||||||
|
|
||||||
|
public ArtemisMode getMode() {
|
||||||
|
return this.mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(ArtemisMode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return this.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Embedded getEmbedded() {
|
||||||
|
return this.embedded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable embedded mode if the Artemis server APIs are available.
|
||||||
|
*/
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String, Object>();
|
||||||
|
parameters.put(TransportConstants.SERVER_ID_PROP_NAME, getServerId());
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.jta.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
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||||
|
@ConditionalOnClass(TransactionManager.class)
|
||||||
|
@ConditionalOnBean(XAConnectionFactoryWrapper.class)
|
||||||
|
class ArtemisXAConnectionFactoryConfiguration {
|
||||||
|
|
||||||
|
@Primary
|
||||||
|
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
|
||||||
|
public ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory,
|
||||||
|
ArtemisProperties properties, XAConnectionFactoryWrapper wrapper)
|
||||||
|
throws Exception {
|
||||||
|
return wrapper.wrapConnectionFactory(new ArtemisConnectionFactoryFactory(
|
||||||
|
beanFactory, properties)
|
||||||
|
.createConnectionFactory(ActiveMQXAConnectionFactory.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConnectionFactory nonXaJmsConnectionFactory(ListableBeanFactory beanFactory,
|
||||||
|
ArtemisProperties properties) {
|
||||||
|
return new ArtemisConnectionFactoryFactory(beanFactory, properties)
|
||||||
|
.createConnectionFactory(ActiveMQXAConnectionFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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;
|
@ -0,0 +1,421 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.util.UUID;
|
||||||
|
|
||||||
|
import javax.jms.Destination;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.Message;
|
||||||
|
import javax.jms.Session;
|
||||||
|
import javax.jms.TextMessage;
|
||||||
|
|
||||||
|
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.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.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.jms.core.JmsTemplate;
|
||||||
|
import org.springframework.jms.core.MessageCreator;
|
||||||
|
import org.springframework.jms.core.SessionCallback;
|
||||||
|
import org.springframework.jms.support.destination.DestinationResolver;
|
||||||
|
import org.springframework.jms.support.destination.DynamicDestinationResolver;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ArtemisAutoConfiguration}.
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
public class ArtemisAutoConfigurationTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final TemporaryFolder folder = new TemporaryFolder();
|
||||||
|
|
||||||
|
private AnnotationConfigApplicationContext context;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
if (this.context != null) {
|
||||||
|
this.context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nativeConnectionFactory() {
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.mode:native");
|
||||||
|
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
|
||||||
|
ActiveMQConnectionFactory connectionFactory = this.context
|
||||||
|
.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertEquals(jmsTemplate.getConnectionFactory(), connectionFactory);
|
||||||
|
assertNettyConnectionFactory(connectionFactory, "localhost", 61616);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nativeConnectionFactoryCustomHost() {
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.mode:native",
|
||||||
|
"spring.artemis.host:192.168.1.144", "spring.artemis.port:9876");
|
||||||
|
ActiveMQConnectionFactory connectionFactory = this.context
|
||||||
|
.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertNettyConnectionFactory(connectionFactory, "192.168.1.144", 9876);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedConnectionFactory() {
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.mode:embedded");
|
||||||
|
ArtemisProperties properties = this.context.getBean(ArtemisProperties.class);
|
||||||
|
assertEquals(ArtemisMode.EMBEDDED, properties.getMode());
|
||||||
|
assertEquals(1, this.context.getBeansOfType(EmbeddedJMS.class).size());
|
||||||
|
org.apache.activemq.artemis.core.config.Configuration configuration = this.context
|
||||||
|
.getBean(org.apache.activemq.artemis.core.config.Configuration.class);
|
||||||
|
assertFalse("Persistence disabled by default",
|
||||||
|
configuration.isPersistenceEnabled());
|
||||||
|
assertFalse("Security disabled by default", configuration.isSecurityEnabled());
|
||||||
|
|
||||||
|
ActiveMQConnectionFactory connectionFactory = this.context
|
||||||
|
.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertInVmConnectionFactory(connectionFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedConnectionFactoryByDefault() {
|
||||||
|
// No mode is specified
|
||||||
|
load(EmptyConfiguration.class);
|
||||||
|
assertEquals(1, this.context.getBeansOfType(EmbeddedJMS.class).size());
|
||||||
|
org.apache.activemq.artemis.core.config.Configuration configuration = this.context
|
||||||
|
.getBean(org.apache.activemq.artemis.core.config.Configuration.class);
|
||||||
|
assertFalse("Persistence disabled by default",
|
||||||
|
configuration.isPersistenceEnabled());
|
||||||
|
assertFalse("Security disabled by default", configuration.isSecurityEnabled());
|
||||||
|
|
||||||
|
ActiveMQConnectionFactory connectionFactory = this.context
|
||||||
|
.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertInVmConnectionFactory(connectionFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nativeConnectionFactoryIfEmbeddedServiceDisabledExplicitly() {
|
||||||
|
// No mode is specified
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.embedded.enabled:false");
|
||||||
|
assertEquals(0, this.context.getBeansOfType(EmbeddedJMS.class).size());
|
||||||
|
ActiveMQConnectionFactory connectionFactory = this.context
|
||||||
|
.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertNettyConnectionFactory(connectionFactory, "localhost", 61616);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedConnectionFactorEvenIfEmbeddedServiceDisabled() {
|
||||||
|
// No mode is specified
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.mode:embedded",
|
||||||
|
"spring.artemis.embedded.enabled:false");
|
||||||
|
assertEquals(0, this.context.getBeansOfType(EmbeddedJMS.class).size());
|
||||||
|
ActiveMQConnectionFactory connectionFactory = this.context
|
||||||
|
.getBean(ActiveMQConnectionFactory.class);
|
||||||
|
assertInVmConnectionFactory(connectionFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedServerWithDestinations() {
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.embedded.queues=Queue1,Queue2",
|
||||||
|
"spring.artemis.embedded.topics=Topic1");
|
||||||
|
DestinationChecker checker = new DestinationChecker(this.context);
|
||||||
|
checker.checkQueue("Queue1", true);
|
||||||
|
checker.checkQueue("Queue2", true);
|
||||||
|
checker.checkQueue("QueueDoesNotExist", true);
|
||||||
|
checker.checkTopic("Topic1", true);
|
||||||
|
checker.checkTopic("TopicDoesNotExist", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedServerWithDestinationConfig() {
|
||||||
|
load(DestinationConfiguration.class);
|
||||||
|
DestinationChecker checker = new DestinationChecker(this.context);
|
||||||
|
checker.checkQueue("sampleQueue", true);
|
||||||
|
checker.checkTopic("sampleTopic", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedServiceWithCustomJmsConfiguration() {
|
||||||
|
// Ignored with custom config
|
||||||
|
load(CustomJmsConfiguration.class, "spring.artemis.embedded.queues=Queue1,Queue2");
|
||||||
|
DestinationChecker checker = new DestinationChecker(this.context);
|
||||||
|
checker.checkQueue("custom", true); // See CustomJmsConfiguration
|
||||||
|
checker.checkQueue("Queue1", true);
|
||||||
|
checker.checkQueue("Queue2", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedServiceWithCustomArtemisConfiguration() {
|
||||||
|
load(CustomArtemisConfiguration.class);
|
||||||
|
org.apache.activemq.artemis.core.config.Configuration configuration = this.context
|
||||||
|
.getBean(org.apache.activemq.artemis.core.config.Configuration.class);
|
||||||
|
assertEquals("customFooBar", configuration.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void embeddedWithPersistentMode() throws IOException, JMSException {
|
||||||
|
File dataFolder = this.folder.newFolder();
|
||||||
|
|
||||||
|
// Start the server and post a message to some queue
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.embedded.queues=TestQueue",
|
||||||
|
"spring.artemis.embedded.persistent:true",
|
||||||
|
"spring.artemis.embedded.dataDirectory:" + dataFolder.getAbsolutePath());
|
||||||
|
|
||||||
|
final String msgId = UUID.randomUUID().toString();
|
||||||
|
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
|
||||||
|
jmsTemplate.send("TestQueue", new MessageCreator() {
|
||||||
|
@Override
|
||||||
|
public Message createMessage(Session session) throws JMSException {
|
||||||
|
return session.createTextMessage(msgId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.context.close(); // Shutdown the broker
|
||||||
|
|
||||||
|
// Start the server again and check if our message is still here
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.embedded.queues=TestQueue",
|
||||||
|
"spring.artemis.embedded.persistent:true",
|
||||||
|
"spring.artemis.embedded.dataDirectory:" + dataFolder.getAbsolutePath());
|
||||||
|
|
||||||
|
JmsTemplate jmsTemplate2 = this.context.getBean(JmsTemplate.class);
|
||||||
|
jmsTemplate2.setReceiveTimeout(1000L);
|
||||||
|
Message message = jmsTemplate2.receive("TestQueue");
|
||||||
|
assertNotNull("No message on persistent queue", message);
|
||||||
|
assertEquals("Invalid message received on queue", msgId,
|
||||||
|
((TextMessage) message).getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void severalEmbeddedBrokers() {
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.embedded.queues=Queue1");
|
||||||
|
AnnotationConfigApplicationContext anotherContext = doLoad(
|
||||||
|
EmptyConfiguration.class, "spring.artemis.embedded.queues=Queue2");
|
||||||
|
try {
|
||||||
|
ArtemisProperties properties = this.context.getBean(ArtemisProperties.class);
|
||||||
|
ArtemisProperties anotherProperties = anotherContext
|
||||||
|
.getBean(ArtemisProperties.class);
|
||||||
|
assertTrue("ServerId should not match", properties.getEmbedded()
|
||||||
|
.getServerId() < anotherProperties.getEmbedded().getServerId());
|
||||||
|
|
||||||
|
DestinationChecker checker = new DestinationChecker(this.context);
|
||||||
|
checker.checkQueue("Queue1", true);
|
||||||
|
checker.checkQueue("Queue2", true);
|
||||||
|
|
||||||
|
DestinationChecker anotherChecker = new DestinationChecker(anotherContext);
|
||||||
|
anotherChecker.checkQueue("Queue2", true);
|
||||||
|
anotherChecker.checkQueue("Queue1", true);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
anotherContext.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connectToASpecificEmbeddedBroker() {
|
||||||
|
load(EmptyConfiguration.class, "spring.artemis.embedded.serverId=93",
|
||||||
|
"spring.artemis.embedded.queues=Queue1");
|
||||||
|
AnnotationConfigApplicationContext anotherContext = doLoad(
|
||||||
|
EmptyConfiguration.class, "spring.artemis.mode=embedded",
|
||||||
|
"spring.artemis.embedded.serverId=93", // Connect to the "main" broker
|
||||||
|
"spring.artemis.embedded.enabled=false"); // do not start a specific one
|
||||||
|
try {
|
||||||
|
DestinationChecker checker = new DestinationChecker(this.context);
|
||||||
|
checker.checkQueue("Queue1", true);
|
||||||
|
|
||||||
|
DestinationChecker anotherChecker = new DestinationChecker(anotherContext);
|
||||||
|
anotherChecker.checkQueue("Queue1", true);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
anotherContext.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransportConfiguration assertInVmConnectionFactory(
|
||||||
|
ActiveMQConnectionFactory connectionFactory) {
|
||||||
|
TransportConfiguration transportConfig = getSingleTransportConfiguration(connectionFactory);
|
||||||
|
assertEquals(InVMConnectorFactory.class.getName(),
|
||||||
|
transportConfig.getFactoryClassName());
|
||||||
|
return transportConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransportConfiguration assertNettyConnectionFactory(
|
||||||
|
ActiveMQConnectionFactory connectionFactory, String host, int port) {
|
||||||
|
TransportConfiguration transportConfig = getSingleTransportConfiguration(connectionFactory);
|
||||||
|
assertEquals(NettyConnectorFactory.class.getName(),
|
||||||
|
transportConfig.getFactoryClassName());
|
||||||
|
assertEquals(host, transportConfig.getParams().get("host"));
|
||||||
|
assertEquals(port, transportConfig.getParams().get("port"));
|
||||||
|
return transportConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransportConfiguration getSingleTransportConfiguration(
|
||||||
|
ActiveMQConnectionFactory connectionFactory) {
|
||||||
|
TransportConfiguration[] transportConfigurations = connectionFactory
|
||||||
|
.getServerLocator().getStaticTransportConfigurations();
|
||||||
|
assertEquals(1, transportConfigurations.length);
|
||||||
|
return transportConfigurations[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load(Class<?> config, String... environment) {
|
||||||
|
this.context = doLoad(config, environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AnnotationConfigApplicationContext doLoad(Class<?> config,
|
||||||
|
String... environment) {
|
||||||
|
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||||
|
applicationContext.register(config);
|
||||||
|
applicationContext.register(ArtemisAutoConfigurationWithoutXA.class,
|
||||||
|
JmsAutoConfiguration.class);
|
||||||
|
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||||
|
applicationContext.refresh();
|
||||||
|
return applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DestinationChecker {
|
||||||
|
|
||||||
|
private final JmsTemplate jmsTemplate;
|
||||||
|
|
||||||
|
private final DestinationResolver destinationResolver;
|
||||||
|
|
||||||
|
private DestinationChecker(ApplicationContext applicationContext) {
|
||||||
|
this.jmsTemplate = applicationContext.getBean(JmsTemplate.class);
|
||||||
|
this.destinationResolver = new DynamicDestinationResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkQueue(String name, boolean shouldExist) {
|
||||||
|
checkDestination(name, false, shouldExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkTopic(String name, boolean shouldExist) {
|
||||||
|
checkDestination(name, true, shouldExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkDestination(final String name, final boolean pubSub,
|
||||||
|
final boolean shouldExist) {
|
||||||
|
this.jmsTemplate.execute(new SessionCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void doInJms(Session session) throws JMSException {
|
||||||
|
try {
|
||||||
|
Destination destination = DestinationChecker.this.destinationResolver
|
||||||
|
.resolveDestinationName(session, name, pubSub);
|
||||||
|
if (!shouldExist) {
|
||||||
|
throw new IllegalStateException("Destination '" + name
|
||||||
|
+ "' was not expected but got " + destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JMSException e) {
|
||||||
|
if (shouldExist) {
|
||||||
|
throw new IllegalStateException("Destination '" + name
|
||||||
|
+ "' was expected but got " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class EmptyConfiguration {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected 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
|
||||||
|
protected static class CustomJmsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JMSConfiguration myJmsConfiguration() {
|
||||||
|
JMSConfiguration config = new JMSConfigurationImpl();
|
||||||
|
JMSQueueConfiguration jmsQueueConfiguration = new JMSQueueConfigurationImpl();
|
||||||
|
jmsQueueConfiguration.setName("custom");
|
||||||
|
jmsQueueConfiguration.setDurable(false);
|
||||||
|
config.getQueueConfigurations().add(jmsQueueConfiguration);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class CustomArtemisConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ArtemisConfigurationCustomizer myArtemisCustomize() {
|
||||||
|
return new ArtemisConfigurationCustomizer() {
|
||||||
|
@Override
|
||||||
|
public void customize(
|
||||||
|
org.apache.activemq.artemis.core.config.Configuration configuration) {
|
||||||
|
configuration.setClusterPassword("Foobar");
|
||||||
|
configuration.setName("customFooBar");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties(ArtemisProperties.class)
|
||||||
|
@Import({ ArtemisEmbeddedServerConfiguration.class,
|
||||||
|
ArtemisConnectionFactoryConfiguration.class })
|
||||||
|
protected static class ArtemisAutoConfigurationWithoutXA {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* http://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.JournalType;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ArtemisEmbeddedConfigurationFactory}
|
||||||
|
*
|
||||||
|
* @author Eddú Meléndez
|
||||||
|
* @author Stephane Nicol
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class ArtemisEmbeddedConfigurationFactoryTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public 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")));
|
||||||
|
assertThat(configuration.getJournalDirectory(), endsWith("/journal"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void persistenceSetup() {
|
||||||
|
ArtemisProperties properties = new ArtemisProperties();
|
||||||
|
properties.getEmbedded().setPersistent(true);
|
||||||
|
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties)
|
||||||
|
.createConfiguration();
|
||||||
|
assertThat(configuration.isPersistenceEnabled(), equalTo(true));
|
||||||
|
assertThat(configuration.getJournalType(), equalTo(JournalType.NIO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void generatedClusterPassword() throws Exception {
|
||||||
|
ArtemisProperties properties = new ArtemisProperties();
|
||||||
|
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties)
|
||||||
|
.createConfiguration();
|
||||||
|
assertThat(configuration.getClusterPassword().length(), equalTo(36));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void specificClusterPassword() throws Exception {
|
||||||
|
ArtemisProperties properties = new ArtemisProperties();
|
||||||
|
properties.getEmbedded().setClusterPassword("password");
|
||||||
|
Configuration configuration = new ArtemisEmbeddedConfigurationFactory(properties)
|
||||||
|
.createConfiguration();
|
||||||
|
assertThat(configuration.getClusterPassword(), equalTo("password"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starters</artifactId>
|
||||||
|
<version>1.3.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>spring-boot-starter-artemis</artifactId>
|
||||||
|
<name>Spring Boot Artemis Starter</name>
|
||||||
|
<description>Spring Boot Artemis Starter</description>
|
||||||
|
<url>http://projects.spring.io/spring-boot/</url>
|
||||||
|
<organization>
|
||||||
|
<name>Pivotal Software, Inc.</name>
|
||||||
|
<url>http://www.spring.io</url>
|
||||||
|
</organization>
|
||||||
|
<properties>
|
||||||
|
<main.basedir>${basedir}/../..</main.basedir>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-jms</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.activemq</groupId>
|
||||||
|
<artifactId>artemis-jms-client</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1 @@
|
|||||||
|
provides: artemis-jms-client,spring-jms
|
Loading…
Reference in New Issue