diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfiguration.java index e1e524dc3e..ce64f95cb4 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfiguration.java @@ -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)); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQProperties.java index f1dea8aa27..d13e9a201d 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQProperties.java @@ -70,7 +70,7 @@ public class HornetQProperties { */ public static class Embedded { - private boolean enabled; + private boolean enabled = true; private boolean persistent; diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfigurationTests.java index 90d116abc9..cea134d494 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQAutoConfigurationTests.java @@ -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); + + 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 embeddedConnectionFactoryIfEmbeddedServiceEnabled() { - // No mode enabled, embedded server required - load(EmptyConfiguration.class, "spring.hornetq.embedded.enabled:true"); + 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()); diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 5c1c815a90..8905da74cb 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -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 diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index e18733ccc3..7e6c575b6c 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -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.