Browse Source
* gh-3154: Document Apache Artemis support Add Apache Artemis Starter POM Add Apache Artemis supportpull/3243/merge
22 changed files with 1457 additions and 27 deletions
@ -0,0 +1,53 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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> |
||||
Loading…
Reference in new issue