Use an embed HornetQ broker by default

This commit changes the default behavior of the HornetQ auto
configuration. Prior to this commit, an embedded broker was only
started when it was requested explicitly by a configuration option.

This is inconsistent with the ActiveMQ support and boot favors the
easiest route. If the necessary classes are available, HornetQ is
embedded in the application by default.

Fixes gh-1029
This commit is contained in:
Stephane Nicoll 2014-06-04 20:15:35 +02:00
parent d6718025e6
commit 726991c144
5 changed files with 68 additions and 42 deletions

View File

@ -42,8 +42,8 @@ import org.hornetq.jms.server.embedded.EmbeddedJMS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -53,12 +53,13 @@ import org.springframework.util.ClassUtils;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} to integrate with an HornetQ broker. Connect by default to a broker
* available on the local machine with the default settings. If the necessary classes are
* present, the broker can also be embedded in the application itself.
* Auto-configuration} to integrate with an HornetQ 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 Stephane Nicoll
* @since 1.1.0
* @see HornetQProperties
*/
@Configuration
@AutoConfigureBefore(JmsAutoConfiguration.class)
@ -73,9 +74,9 @@ public class HornetQAutoConfiguration {
/**
* Create the {@link ConnectionFactory} to use if none is provided. If no
* {@linkplain HornetQProperties#getMode() mode} has been explicitly set, connect to
* the embedded server if it has been requested or to a broker available on the local
* machine with the default settings otherwise.
* {@linkplain HornetQProperties#getMode() mode} has been explicitly set, start an
* embedded server unless it has been explicitly disabled, connect to a broker
* available on the local machine with the default settings otherwise.
*/
@Bean
@ConditionalOnMissingBean
@ -131,7 +132,7 @@ public class HornetQAutoConfiguration {
*/
@Configuration
@ConditionalOnClass(name = EMBEDDED_JMS_CLASS)
@ConditionalOnProperty(prefix = "spring.hornetq.embedded", value = "enabled")
@ConditionalOnExpression("'${spring.hornetq.embedded.enabled:true}' == 'true'")
static class EmbeddedServerConfiguration {
@Autowired
@ -159,14 +160,14 @@ public class HornetQAutoConfiguration {
org.hornetq.core.config.Configuration configuration,
JMSConfiguration jmsConfiguration) {
EmbeddedJMS server = new EmbeddedJMS();
applyCustomizers(configuration);
customize(configuration);
server.setConfiguration(configuration);
server.setJmsConfiguration(jmsConfiguration);
server.setRegistry(new HornetQNoOpBindingRegistry());
return server;
}
private void applyCustomizers(org.hornetq.core.config.Configuration configuration) {
private void customize(org.hornetq.core.config.Configuration configuration) {
if (this.configurationCustomizers != null) {
AnnotationAwareOrderComparator.sort(this.configurationCustomizers);
for (HornetQConfigurationCustomizer customizer : this.configurationCustomizers) {
@ -182,7 +183,7 @@ public class HornetQAutoConfiguration {
addAll(configuration.getQueueConfigurations(), this.queuesConfiguration);
addAll(configuration.getTopicConfigurations(), this.topicsConfiguration);
addQueues(configuration, this.properties.getEmbedded().getQueues());
addTopis(configuration, this.properties.getEmbedded().getTopics());
addTopics(configuration, this.properties.getEmbedded().getTopics());
return configuration;
}
@ -201,7 +202,7 @@ public class HornetQAutoConfiguration {
}
}
private void addTopis(JMSConfiguration configuration, String[] topics) {
private void addTopics(JMSConfiguration configuration, String[] topics) {
for (String topic : topics) {
configuration.getTopicConfigurations().add(
new TopicConfigurationImpl(topic, "/topic/" + topic));

View File

@ -70,7 +70,7 @@ public class HornetQProperties {
*/
public static class Embedded {
private boolean enabled;
private boolean enabled = true;
private boolean persistent;

View File

@ -43,10 +43,6 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.hornetq.HornetQAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.hornetq.HornetQConfigurationCustomizer;
import org.springframework.boot.autoconfigure.jms.hornetq.HornetQMode;
import org.springframework.boot.autoconfigure.jms.hornetq.HornetQProperties;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -93,7 +89,8 @@ public class HornetQAutoConfigurationTests {
@Test
public void nativeConnectionFactoryCustomHost() {
load(EmptyConfiguration.class, "spring.hornetq.host:192.168.1.144",
load(EmptyConfiguration.class, "spring.hornetq.mode:native",
"spring.hornetq.host:192.168.1.144",
"spring.hornetq.port:9876");
HornetQConnectionFactory connectionFactory = this.context
.getBean(HornetQConnectionFactory.class);
@ -102,8 +99,7 @@ public class HornetQAutoConfigurationTests {
@Test
public void embeddedConnectionFactory() {
load(EmptyConfiguration.class, "spring.hornetq.mode:embedded",
"spring.hornetq.embedded.enabled:true");
load(EmptyConfiguration.class, "spring.hornetq.mode:embedded");
HornetQProperties properties = this.context.getBean(HornetQProperties.class);
assertEquals(HornetQMode.EMBEDDED, properties.getMode());
@ -121,26 +117,52 @@ public class HornetQAutoConfigurationTests {
}
@Test
public void nativeConnectionFactoryByDefault() {
public void embeddedConnectionFactoryByDefault() {
// No mode is specified
load(EmptyConfiguration.class);
HornetQConnectionFactory connectionFactory = this.context
.getBean(HornetQConnectionFactory.class);
assertNettyConnectionFactory(connectionFactory, "localhost", 5445);
}
@Test
public void embeddedConnectionFactoryIfEmbeddedServiceEnabled() {
// No mode enabled, embedded server required
load(EmptyConfiguration.class, "spring.hornetq.embedded.enabled:true");
assertEquals(1, this.context.getBeansOfType(EmbeddedJMS.class).size());
org.hornetq.core.config.Configuration configuration = this.context
.getBean(org.hornetq.core.config.Configuration.class);
assertFalse("Persistence disabled by default",
configuration.isPersistenceEnabled());
assertFalse("Security disabled by default", configuration.isSecurityEnabled());
HornetQConnectionFactory connectionFactory = this.context
.getBean(HornetQConnectionFactory.class);
assertInVmConnectionFactory(connectionFactory);
}
@Test
public void nativeConnectionFactoryIfEmbeddedServiceDisabledExplicitly() {
// No mode is specified
load(EmptyConfiguration.class, "spring.hornetq.embedded.enabled:false");
assertEquals(0, this.context.getBeansOfType(EmbeddedJMS.class).size());
HornetQConnectionFactory connectionFactory = this.context
.getBean(HornetQConnectionFactory.class);
assertNettyConnectionFactory(connectionFactory, "localhost", 5445);
}
@Test
public void embeddedConnectionFactorEvenIfEmbeddedServiceDisabled() {
// No mode is specified
load(EmptyConfiguration.class,
"spring.hornetq.mode:embedded",
"spring.hornetq.embedded.enabled:false");
assertEquals(0, this.context.getBeansOfType(EmbeddedJMS.class).size());
HornetQConnectionFactory connectionFactory = this.context
.getBean(HornetQConnectionFactory.class);
assertInVmConnectionFactory(connectionFactory);
}
@Test
public void embeddedServerWithDestinations() {
load(EmptyConfiguration.class, "spring.hornetq.embedded.enabled:true",
load(EmptyConfiguration.class,
"spring.hornetq.embedded.queues=Queue1,Queue2",
"spring.hornetq.embedded.topics=Topic1");
@ -155,7 +177,7 @@ public class HornetQAutoConfigurationTests {
@Test
public void embeddedServerWithDestinationConfig() {
load(DestinationConfiguration.class, "spring.hornetq.embedded.enabled:true");
load(DestinationConfiguration.class);
DestinationChecker checker = new DestinationChecker(this.context);
checker.checkQueue("sampleQueue", true);
@ -164,7 +186,7 @@ public class HornetQAutoConfigurationTests {
@Test
public void embeddedServiceWithCustomJmsConfiguration() {
load(CustomJmsConfiguration.class, "spring.hornetq.embedded.enabled:true",
load(CustomJmsConfiguration.class,
"spring.hornetq.embedded.queues=Queue1,Queue2"); // Ignored with custom
// config
DestinationChecker checker = new DestinationChecker(this.context);
@ -176,7 +198,7 @@ public class HornetQAutoConfigurationTests {
@Test
public void embeddedServiceWithCustomHornetQConfiguration() {
load(CustomHornetQConfiguration.class, "spring.hornetq.embedded.enabled:true");
load(CustomHornetQConfiguration.class);
org.hornetq.core.config.Configuration configuration = this.context
.getBean(org.hornetq.core.config.Configuration.class);
assertEquals("customFooBar", configuration.getName());
@ -187,7 +209,7 @@ public class HornetQAutoConfigurationTests {
File dataFolder = this.folder.newFolder();
// Start the server and post a message to some queue
load(EmptyConfiguration.class, "spring.hornetq.embedded.enabled:true",
load(EmptyConfiguration.class,
"spring.hornetq.embedded.queues=TestQueue",
"spring.hornetq.embedded.persistent:true",
"spring.hornetq.embedded.dataDirectory:" + dataFolder.getAbsolutePath());
@ -203,7 +225,7 @@ public class HornetQAutoConfigurationTests {
this.context.close(); // Shutdown the broker
// Start the server again and check if our message is still here
load(EmptyConfiguration.class, "spring.hornetq.embedded.enabled:true",
load(EmptyConfiguration.class,
"spring.hornetq.embedded.queues=TestQueue",
"spring.hornetq.embedded.persistent:true",
"spring.hornetq.embedded.dataDirectory:" + dataFolder.getAbsolutePath());

View File

@ -256,7 +256,7 @@ content into your application; rather pick only the properties that you need.
spring.hornetq.embedded.data-directory= # location of data content (when persistence is enabled)
spring.hornetq.embedded.queues= # comma separate queues to create on startup
spring.hornetq.embedded.topics= # comma separate topics to create on startup
spring.hornetq.embedded.cluster-password = # customer password (randomly generated by default)
spring.hornetq.embedded.cluster-password= # customer password (randomly generated by default)
# JMS ({sc-spring-boot-autoconfigure}/jms/JmsTemplateProperties.{sc-ext}[JmsTemplateProperties])
spring.jms.pub-sub-domain= # false for queue (default), true for topic

View File

@ -1702,11 +1702,14 @@ components require a `ConnectionFactory` to operate.
==== HornetQ support
Spring Boot can auto-configure a `ConnectionFactory` when it detects that
HornetQ is available on the classpath. By default, a `ConnectionFactory` using
the `netty` transport protocol is configured, connecting to a broker running on
the local machine with the default settings. It is also possible to connect to
a running broker provided in the container or even embed the container in the
application if the necessary classes are present.
HornetQ is available on the classpath. If the broker is present, an embedded
broker is started and configured automatically unless the mode property has
been explicitly set. The supported modes are: `embedded` (to make explicit
that an embedded broker is required and should lead to an error if the broker
is not available in the classpath), and `native` to connect to a broker
using the the `netty` transport protocol. When the latter is configured, boot
configures a `ConnectionFactory` connecting to a broker running on the local
machine with the default settings.
NOTE: if you are using `spring-boot-starter-hornetq` the necessary dependencies
to connect to an existing HornetQ instance are provided, as well as the Spring
@ -1742,7 +1745,7 @@ names provided through configuration.
==== ActiveMQ support
Spring Boot can also configure a `ConnectionFactory` when it detects that
ActiveMQ is available on the classpath. If the complete broker is available,
ActiveMQ is available on the classpath. If the broker is present,
an embedded broker is started and configured automatically if no broker URL
is specified through configuration.