You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ro...@apache.org on 2024/01/19 11:40:48 UTC

(activemq-artemis) branch main updated: ARTEMIS-4552 Config all connection-router settings by using broker properties

This is an automated email from the ASF dual-hosted git repository.

robbie pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/main by this push:
     new 2b331427d8 ARTEMIS-4552 Config all connection-router settings by using broker properties
2b331427d8 is described below

commit 2b331427d8e2278064314a9412ae0adcef144ce0
Author: Domenico Francesco Bruscino <br...@apache.org>
AuthorDate: Thu Jan 18 13:41:16 2024 +0100

    ARTEMIS-4552 Config all connection-router settings by using broker properties
---
 .../core/config/impl/ConfigurationImpl.java        | 33 ++++++++-
 .../core/config/impl/ConfigurationImplTest.java    | 81 +++++++++++++++++++++-
 2 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
index f2c9b6ae6b..993717c45f 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
@@ -614,6 +614,31 @@ public class ConfigurationImpl implements Configuration, Serializable {
    public void populateWithProperties(final Object target, final String propsId, Map<String, Object> beanProperties) throws InvocationTargetException, IllegalAccessException {
       CollectionAutoFillPropertiesUtil autoFillCollections = new CollectionAutoFillPropertiesUtil(getBrokerPropertiesRemoveValue(beanProperties));
       BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), autoFillCollections) {
+
+         // initialize the given property of the given bean with a new instance of the property class
+         private Object initProperty(Object bean, String name) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
+            PropertyDescriptor descriptor = getPropertyUtils().getPropertyDescriptor(bean, name);
+            if (descriptor == null) {
+               throw new InvocationTargetException(null, "No accessor method descriptor for: " + name + " on: " + bean.getClass());
+            }
+
+            Method writeMethod = descriptor.getWriteMethod();
+            if (writeMethod == null) {
+               throw new InvocationTargetException(null, "No Write method for: " + name + " on: " + bean.getClass());
+            }
+
+            Object propertyInstance;
+            try {
+               propertyInstance = descriptor.getPropertyType().getDeclaredConstructor().newInstance();
+            } catch (InstantiationException e) {
+               throw new InvocationTargetException(e);
+            }
+
+            writeMethod.invoke(bean, propertyInstance);
+
+            return propertyInstance;
+         }
+
          // override to treat missing properties as errors, not skip as the default impl does
          @Override
          public void setProperty(final Object bean, String name, final Object value) throws InvocationTargetException, IllegalAccessException {
@@ -626,10 +651,12 @@ public class ConfigurationImpl implements Configuration, Serializable {
                final Resolver resolver = getPropertyUtils().getResolver();
                while (resolver.hasNested(name)) {
                   try {
-                     target = getPropertyUtils().getProperty(target, resolver.next(name));
-                     if (target == null) {
-                        throw new InvocationTargetException(null, "Resolved nested property for:" + name + ", on: " + bean + " was null");
+                     String nextName = resolver.next(name);
+                     Object nextTarget = getPropertyUtils().getProperty(target, nextName);
+                     if (nextTarget == null) {
+                        nextTarget = initProperty(target, nextName);
                      }
+                     target = nextTarget;
                      name = resolver.remove(name);
                   } catch (final NoSuchMethodException e) {
                      throw new InvocationTargetException(e, "No getter for property:" + name + ", on: " + bean);
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
index a567984fae..e0b1ded173 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
@@ -53,6 +53,7 @@ import org.apache.activemq.artemis.core.config.federation.FederationAddressPolic
 import org.apache.activemq.artemis.core.config.federation.FederationPolicySet;
 import org.apache.activemq.artemis.core.config.federation.FederationQueuePolicyConfiguration;
 import org.apache.activemq.artemis.core.config.ha.PrimaryOnlyPolicyConfiguration;
+import org.apache.activemq.artemis.core.config.routing.ConnectionRouterConfiguration;
 import org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration;
 import org.apache.activemq.artemis.core.deployers.impl.FileConfigurationParser;
 import org.apache.activemq.artemis.core.io.SequentialFileFactory;
@@ -68,6 +69,7 @@ import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancing
 import org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin;
 import org.apache.activemq.artemis.core.server.routing.KeyType;
 import org.apache.activemq.artemis.core.server.routing.policies.ConsistentHashModuloPolicy;
+import org.apache.activemq.artemis.core.server.routing.policies.ConsistentHashPolicy;
 import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
 import org.apache.activemq.artemis.core.settings.impl.DeletionPolicy;
 import org.apache.activemq.artemis.core.settings.impl.ResourceLimitSettings;
@@ -719,11 +721,42 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
       insertionOrderedProperties.put("connectionRouters.autoShard.policyConfiguration", ConsistentHashModuloPolicy.NAME);
       insertionOrderedProperties.put("connectionRouters.autoShard.policyConfiguration.properties." + ConsistentHashModuloPolicy.MODULO, 2);
 
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.keyType", KeyType.CLIENT_ID);
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.keyFilter", "^.{3}");
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.policyConfiguration", ConsistentHashPolicy.NAME);
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.poolConfiguration.username", "guest-username");
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.poolConfiguration.password", "guest-password");
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.poolConfiguration.quorumSize", "2");
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.poolConfiguration.localTargetEnabled", Boolean.TRUE.toString());
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.poolConfiguration.discoveryGroupName", "discovery-group-1");
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.cacheConfiguration.persisted", Boolean.TRUE.toString());
+      insertionOrderedProperties.put("connectionRouters.symmetricRedirect.cacheConfiguration.timeout", "1234");
+
       configuration.parsePrefixedProperties(insertionOrderedProperties, null);
 
-      Assert.assertEquals(1, configuration.getConnectionRouters().size());
-      Assert.assertEquals(KeyType.CLIENT_ID, configuration.getConnectionRouters().get(0).getKeyType());
-      Assert.assertEquals("2", configuration.getConnectionRouters().get(0).getPolicyConfiguration().getProperties().get(ConsistentHashModuloPolicy.MODULO));
+      Assert.assertEquals(2, configuration.getConnectionRouters().size());
+
+      ConnectionRouterConfiguration autoShardConfig =  configuration.getConnectionRouters().stream().filter(
+         connectionRouterConfig -> "autoShard".equals(connectionRouterConfig.getName())).findFirst().get();
+      Assert.assertEquals(KeyType.CLIENT_ID, autoShardConfig.getKeyType());
+      Assert.assertEquals("2", autoShardConfig.getPolicyConfiguration().getProperties().get(ConsistentHashModuloPolicy.MODULO));
+      Assert.assertNull(autoShardConfig.getCacheConfiguration());
+      Assert.assertNull(autoShardConfig.getPoolConfiguration());
+
+      ConnectionRouterConfiguration symmetricRedirectConfig =  configuration.getConnectionRouters().stream().filter(
+         connectionRouterConfig -> "symmetricRedirect".equals(connectionRouterConfig.getName())).findFirst().get();
+      Assert.assertEquals(KeyType.CLIENT_ID, symmetricRedirectConfig.getKeyType());
+      Assert.assertEquals("^.{3}", symmetricRedirectConfig.getKeyFilter());
+      Assert.assertEquals(ConsistentHashPolicy.NAME, symmetricRedirectConfig.getPolicyConfiguration().getName());
+      Assert.assertNotNull(symmetricRedirectConfig.getPoolConfiguration());
+      Assert.assertEquals("guest-username", symmetricRedirectConfig.getPoolConfiguration().getUsername());
+      Assert.assertEquals("guest-password", symmetricRedirectConfig.getPoolConfiguration().getPassword());
+      Assert.assertEquals(2, symmetricRedirectConfig.getPoolConfiguration().getQuorumSize());
+      Assert.assertEquals(Boolean.TRUE, symmetricRedirectConfig.getPoolConfiguration().isLocalTargetEnabled());
+      Assert.assertEquals("discovery-group-1", symmetricRedirectConfig.getPoolConfiguration().getDiscoveryGroupName());
+      Assert.assertNotNull(symmetricRedirectConfig.getCacheConfiguration());
+      Assert.assertEquals(Boolean.TRUE, symmetricRedirectConfig.getCacheConfiguration().isPersisted());
+      Assert.assertEquals(1234, symmetricRedirectConfig.getCacheConfiguration().getTimeout());
    }
 
    @Test
@@ -2205,6 +2238,48 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
       Assert.assertEquals(4321, configuration.getGlobalMaxSize());
    }
 
+   @Test
+   public void testConfigWithMultipleNullDescendantChildren() throws Throwable {
+      String dummyPropertyPrefix = "dummy.";
+      DummyConfig dummyConfig = new DummyConfig();
+
+      Properties properties = new Properties();
+      properties.put(dummyPropertyPrefix + "childConfig.childConfig.childConfig.intProperty", "1");
+
+      Configuration configuration = new ConfigurationImpl();
+      configuration.parsePrefixedProperties(dummyConfig, "dummy", properties, dummyPropertyPrefix);
+
+      Assert.assertNotNull(dummyConfig.getChildConfig());
+      Assert.assertNotNull(dummyConfig.getChildConfig().getChildConfig());
+      Assert.assertNotNull(dummyConfig.getChildConfig().getChildConfig().getChildConfig());
+      Assert.assertNull(dummyConfig.getChildConfig().getChildConfig().getChildConfig().getChildConfig());
+      Assert.assertEquals(1, dummyConfig.getChildConfig().getChildConfig().getChildConfig().getIntProperty());
+   }
+
+   public static class DummyConfig {
+      private int intProperty;
+
+      private DummyConfig childConfig;
+
+      public int getIntProperty() {
+         return intProperty;
+      }
+
+      public DummyConfig setIntProperty(int intProperty) {
+         this.intProperty = intProperty;
+         return this;
+      }
+
+      public DummyConfig getChildConfig() {
+         return childConfig;
+      }
+
+      public DummyConfig setChildConfig(DummyConfig childConfig) {
+         this.childConfig = childConfig;
+         return this;
+      }
+   }
+
    @Override
    @Before
    public void setUp() throws Exception {