From 99b43cb690e70afd39cc69783e1155a7a7b4e186 Mon Sep 17 00:00:00 2001 From: Justin Bertram Date: Mon, 30 Nov 2020 12:48:33 -0600 Subject: [PATCH 1/2] Allow to configure ActiveMQ Artemis with a broker url See gh-24302 --- .../ArtemisConnectionFactoryFactory.java | 21 +++++++++++++------ .../jms/artemis/ArtemisProperties.java | 20 ++++++++++++++++++ .../ArtemisAutoConfigurationTests.java | 16 ++++++++++++-- .../docs/asciidoc/spring-boot-features.adoc | 11 +++++----- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java index e8b9979189..3b1d7ddf17 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java @@ -40,6 +40,7 @@ import org.springframework.util.StringUtils; * @author Eddú Meléndez * @author Phillip Webb * @author Stephane Nicoll + * @author Justin Bertram */ class ArtemisConnectionFactoryFactory { @@ -127,13 +128,21 @@ class ArtemisConnectionFactoryFactory { private T createNativeConnectionFactory(Class factoryClass) throws Exception { + T connectionFactory; Map params = new HashMap<>(); - params.put(TransportConstants.HOST_PROP_NAME, this.properties.getHost()); - params.put(TransportConstants.PORT_PROP_NAME, this.properties.getPort()); - TransportConfiguration transportConfiguration = new TransportConfiguration( - NettyConnectorFactory.class.getName(), params); - Constructor constructor = factoryClass.getConstructor(boolean.class, TransportConfiguration[].class); - T connectionFactory = constructor.newInstance(false, new TransportConfiguration[] { transportConfiguration }); + String url = this.properties.getBrokerUrl(); + if (StringUtils.hasText(url)) { + Constructor constructor = factoryClass.getConstructor(String.class); + connectionFactory = constructor.newInstance(url); + } + else { + 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 constructor = factoryClass.getConstructor(boolean.class, TransportConfiguration[].class); + connectionFactory = constructor.newInstance(false, new TransportConfiguration[] { transportConfiguration }); + } String user = this.properties.getUser(); if (StringUtils.hasText(user)) { connectionFactory.setUser(user); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java index 1b227f60a7..50103b696a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java @@ -32,6 +32,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty; * * @author Eddú Meléndez * @author Stephane Nicoll + * @author Justin Bertram * @since 1.3.0 */ @ConfigurationProperties(prefix = "spring.artemis") @@ -44,14 +45,25 @@ public class ArtemisProperties { /** * Artemis broker host. + * + * This property is deprecated. Use brokerUrl instead. */ + @Deprecated private String host = "localhost"; /** * Artemis broker port. + * + * This property is deprecated. Use brokerUrl instead. */ + @Deprecated private int port = 61616; + /** + * Artemis broker port. + */ + private String brokerUrl = "tcp://localhost:61616"; + /** * Login user of the broker. */ @@ -91,6 +103,14 @@ public class ArtemisProperties { this.port = port; } + public String getBrokerUrl() { + return this.brokerUrl; + } + + public void setBrokerUrl(String brokerUrl) { + this.brokerUrl = brokerUrl; + } + public String getUser() { return this.user; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java index b93e4a45b5..eb5d9fed36 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java @@ -127,7 +127,15 @@ class ArtemisAutoConfigurationTests { void nativeConnectionFactoryCustomHost() { this.contextRunner.withUserConfiguration(EmptyConfiguration.class) .withPropertyValues("spring.artemis.mode:native", "spring.artemis.host:192.168.1.144", - "spring.artemis.port:9876") + "spring.artemis.port:9876", "spring.artemis.broker-url: ") + .run((context) -> assertNettyConnectionFactory( + getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876)); + } + + @Test + void nativeConnectionFactoryCustomUrl() { + this.contextRunner.withUserConfiguration(EmptyConfiguration.class) + .withPropertyValues("spring.artemis.mode:native", "spring.artemis.broker-url:tcp://192.168.1.144:9876") .run((context) -> assertNettyConnectionFactory( getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876)); } @@ -377,7 +385,11 @@ class ArtemisAutoConfigurationTests { TransportConfiguration transportConfig = getSingleTransportConfiguration(connectionFactory); assertThat(transportConfig.getFactoryClassName()).isEqualTo(NettyConnectorFactory.class.getName()); assertThat(transportConfig.getParams().get("host")).isEqualTo(host); - assertThat(transportConfig.getParams().get("port")).isEqualTo(port); + Object transportConfigPort = transportConfig.getParams().get("port"); + if (transportConfigPort instanceof String) { + transportConfigPort = Integer.parseInt((String) transportConfigPort); + } + assertThat(transportConfigPort).isEqualTo(port); return transportConfig; } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc index ad397b8e2d..6685945359 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc @@ -5739,16 +5739,16 @@ By default, ActiveMQ creates a destination if it does not yet exist so that dest [[boot-features-artemis]] -==== Artemis Support -Spring Boot can auto-configure a `ConnectionFactory` when it detects that https://activemq.apache.org/components/artemis/[Artemis] is available on the classpath. +==== ActiveMQ Artemis Support +Spring Boot can auto-configure a `ConnectionFactory` when it detects that https://activemq.apache.org/components/artemis/[ActiveMQ Artemis] is available on the classpath. If the broker is present, an embedded broker is automatically started and configured (unless the mode property has been explicitly set). The supported modes are `embedded` (to make explicit that an embedded broker is required and that an error should occur if the broker is not available on the classpath) and `native` (to connect to a broker using the `netty` transport protocol). When the latter is configured, Spring Boot configures a `ConnectionFactory` that connects to a broker running on the local machine with the default settings. -NOTE: If you use `spring-boot-starter-artemis`, the necessary dependencies to connect to an existing Artemis instance are provided, as well as the Spring infrastructure to integrate with JMS. +NOTE: If you use `spring-boot-starter-artemis`, the necessary dependencies to connect to an existing ActiveMQ Artemis instance are provided, as well as the Spring infrastructure to integrate with JMS. Adding `org.apache.activemq:artemis-jms-server` to your application lets you use embedded mode. -Artemis configuration is controlled by external configuration properties in `+spring.artemis.*+`. +ActiveMQ Artemis configuration is controlled by external configuration properties in `+spring.artemis.*+`. For example, you might declare the following section in `application.properties`: [source,yaml,indent=0,configprops,configblocks] @@ -5756,8 +5756,7 @@ For example, you might declare the following section in `application.properties` spring: artemis: mode: native - host: "192.168.1.210" - port: 9876 + broker-url: "tcp://192.168.1.210:9876" user: "admin" password: "secret" ---- From 338c8c4fc85d7d99b7d326618cdea5c72b2b8558 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 21 Dec 2020 17:53:10 +0100 Subject: [PATCH 2/2] Polish "Allow to configure ActiveMQ Artemis with a broker url" See gh-24302 --- .../ArtemisConnectionFactoryFactory.java | 37 ++++++++------ .../jms/artemis/ArtemisProperties.java | 49 +++++++++++-------- ...itional-spring-configuration-metadata.json | 4 ++ .../ArtemisAutoConfigurationTests.java | 19 +++++-- 4 files changed, 70 insertions(+), 39 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java index 3b1d7ddf17..62de6fb0ed 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,8 @@ import org.springframework.util.StringUtils; */ class ArtemisConnectionFactoryFactory { + private static final String DEFAULT_BROKER_URL = "tcp://localhost:61616"; + static final String[] EMBEDDED_JMS_CLASSES = { "org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS", "org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ" }; @@ -128,27 +130,32 @@ class ArtemisConnectionFactoryFactory { private T createNativeConnectionFactory(Class factoryClass) throws Exception { - T connectionFactory; - Map params = new HashMap<>(); - String url = this.properties.getBrokerUrl(); - if (StringUtils.hasText(url)) { - Constructor constructor = factoryClass.getConstructor(String.class); - connectionFactory = constructor.newInstance(url); + T connectionFactory = newNativeConnectionFactory(factoryClass); + String user = this.properties.getUser(); + if (StringUtils.hasText(user)) { + connectionFactory.setUser(user); + connectionFactory.setPassword(this.properties.getPassword()); } - else { + return connectionFactory; + } + + @SuppressWarnings("deprecation") + private T newNativeConnectionFactory(Class factoryClass) throws Exception { + // Fallback if the broker url is not set + if (!StringUtils.hasText(this.properties.getBrokerUrl()) && StringUtils.hasText(this.properties.getHost())) { + Map params = new HashMap<>(); params.put(TransportConstants.HOST_PROP_NAME, this.properties.getHost()); params.put(TransportConstants.PORT_PROP_NAME, this.properties.getPort()); TransportConfiguration transportConfiguration = new TransportConfiguration( NettyConnectorFactory.class.getName(), params); Constructor constructor = factoryClass.getConstructor(boolean.class, TransportConfiguration[].class); - connectionFactory = constructor.newInstance(false, new TransportConfiguration[] { transportConfiguration }); + return constructor.newInstance(false, new TransportConfiguration[] { transportConfiguration }); } - String user = this.properties.getUser(); - if (StringUtils.hasText(user)) { - connectionFactory.setUser(user); - connectionFactory.setPassword(this.properties.getPassword()); - } - return connectionFactory; + String brokerUrl = StringUtils.hasText(this.properties.getBrokerUrl()) ? this.properties.getBrokerUrl() + : DEFAULT_BROKER_URL; + Constructor constructor = factoryClass.getConstructor(String.class); + return constructor.newInstance(brokerUrl); + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java index 50103b696a..34fd02b7f4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants; import org.springframework.boot.autoconfigure.jms.JmsPoolConnectionFactoryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.boot.context.properties.NestedConfigurationProperty; /** @@ -44,25 +45,19 @@ public class ArtemisProperties { private ArtemisMode mode; /** - * Artemis broker host. - * - * This property is deprecated. Use brokerUrl instead. + * Artemis broker port. */ - @Deprecated - private String host = "localhost"; + private String brokerUrl; /** - * Artemis broker port. - * - * This property is deprecated. Use brokerUrl instead. + * Artemis broker host. */ - @Deprecated - private int port = 61616; + private String host; /** * Artemis broker port. */ - private String brokerUrl = "tcp://localhost:61616"; + private int port = 61616; /** * Login user of the broker. @@ -87,30 +82,44 @@ public class ArtemisProperties { this.mode = mode; } + public String getBrokerUrl() { + return this.brokerUrl; + } + + public void setBrokerUrl(String brokerUrl) { + this.brokerUrl = brokerUrl; + } + + /** + * Return the host of the broker. + * @return the host + */ + @Deprecated + @DeprecatedConfigurationProperty(replacement = "spring.artemis.broker-url") public String getHost() { return this.host; } + @Deprecated public void setHost(String host) { this.host = host; } + /** + * Return the port of the broker. + * @return the port + */ + @Deprecated + @DeprecatedConfigurationProperty(replacement = "spring.artemis.broker-url") public int getPort() { return this.port; } + @Deprecated public void setPort(int port) { this.port = port; } - public String getBrokerUrl() { - return this.brokerUrl; - } - - public void setBrokerUrl(String brokerUrl) { - this.brokerUrl = brokerUrl; - } - public String getUser() { return this.user; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 40e775faf4..d3ff212ece 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -352,6 +352,10 @@ "description": "JMX name of the application admin MBean.", "defaultValue": "org.springframework.boot:type=Admin,name=SpringApplication" }, + { + "name": "spring.artemis.broker-url", + "defaultValue": "tcp://localhost:61616" + }, { "name": "spring.artemis.pool.maximum-active-session-per-connection", "deprecation": { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java index eb5d9fed36..515a4306bf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java @@ -124,20 +124,31 @@ class ArtemisAutoConfigurationTests { } @Test + void nativeConnectionFactoryCustomBrokerUrl() { + this.contextRunner.withUserConfiguration(EmptyConfiguration.class) + .withPropertyValues("spring.artemis.mode:native", "spring.artemis.broker-url:tcp://192.168.1.144:9876") + .run((context) -> assertNettyConnectionFactory( + getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876)); + } + + @Test + @Deprecated void nativeConnectionFactoryCustomHost() { this.contextRunner.withUserConfiguration(EmptyConfiguration.class) .withPropertyValues("spring.artemis.mode:native", "spring.artemis.host:192.168.1.144", - "spring.artemis.port:9876", "spring.artemis.broker-url: ") + "spring.artemis.port:9876") .run((context) -> assertNettyConnectionFactory( getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876)); } @Test - void nativeConnectionFactoryCustomUrl() { + @Deprecated + void nativeConnectionFactoryCustomBrokerUrlAndHost() { this.contextRunner.withUserConfiguration(EmptyConfiguration.class) - .withPropertyValues("spring.artemis.mode:native", "spring.artemis.broker-url:tcp://192.168.1.144:9876") + .withPropertyValues("spring.artemis.mode:native", "spring.artemis.host:192.168.1.144", + "spring.artemis.port:9876", "spring.artemis.broker-url=tcp://192.168.1.221:6543") .run((context) -> assertNettyConnectionFactory( - getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.144", 9876)); + getActiveMQConnectionFactory(getConnectionFactory(context)), "192.168.1.221", 6543)); } @Test