From b3dea6f4d9ca9586aa1812c0e6e94128bb385278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Tue, 16 Jun 2026 12:08:37 -0700 Subject: [PATCH] Preserve property placeholders when removing/modifying networkConnectors NetworkConnectorProcessor.configMatch compared raw DTO values (still holding ${...} placeholders) against the live NetworkConnector whose attributes had already been resolved by Spring. A connector declared with placeholders could therefore never be matched for removal or modification by the RuntimeConfigurationPlugin. Filter the DTO props through placeHolderUtil before comparing. --- .../plugin/NetworkConnectorProcessor.java | 15 ++++-- .../org/apache/activemq/SpringBeanTest.java | 46 +++++++++++++++++++ ...tableConfig1000-spring-property-one-nc.xml | 38 +++++++++++++++ ...tableConfig1000-spring-property-two-nc.xml | 39 ++++++++++++++++ 4 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-one-nc.xml create mode 100644 activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-two-nc.xml diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java index 6ea145423ba..3793257ae1f 100644 --- a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java +++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java @@ -16,6 +16,7 @@ */ package org.apache.activemq.plugin; +import java.util.Properties; import java.util.TreeMap; import org.apache.activemq.network.DiscoveryNetworkConnector; @@ -63,15 +64,23 @@ public void remove(Object o) { } private boolean configMatch(DtoNetworkConnector dto, NetworkConnector candidate) { - TreeMap dtoProps = new TreeMap(); + Properties dtoProps = new Properties(); IntrospectionSupport.getProperties(dto, dtoProps, null); + // the live candidate has its ${foo} placeholders already resolved, so resolve them on + // the dto side too before comparing — otherwise a connector declared with placeholders + // can never be matched for removal/modification + if (plugin.placeHolderUtil != null) { + plugin.placeHolderUtil.filter(dtoProps); + } TreeMap candidateProps = new TreeMap(); IntrospectionSupport.getProperties(candidate, candidateProps, null); // every dto prop must be present in the candidate - for (String key : dtoProps.keySet()) { - if (!candidateProps.containsKey(key) || !candidateProps.get(key).equals(dtoProps.get(key))) { + for (Object keyObj : dtoProps.keySet()) { + String key = (String) keyObj; + String dtoValue = (String) dtoProps.get(key); + if (!candidateProps.containsKey(key) || !candidateProps.get(key).equals(dtoValue)) { return false; } } diff --git a/activemq-runtime-config/src/test/java/org/apache/activemq/SpringBeanTest.java b/activemq-runtime-config/src/test/java/org/apache/activemq/SpringBeanTest.java index 42e3aad30c6..bdba1119cdd 100644 --- a/activemq-runtime-config/src/test/java/org/apache/activemq/SpringBeanTest.java +++ b/activemq-runtime-config/src/test/java/org/apache/activemq/SpringBeanTest.java @@ -16,9 +16,12 @@ */ package org.apache.activemq; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import javax.management.ObjectName; import org.apache.activemq.network.DiscoveryNetworkConnector; +import org.apache.activemq.network.NetworkConnector; import org.apache.activemq.plugin.RuntimeConfigurationBroker; import org.apache.activemq.plugin.jmx.RuntimeConfigurationViewMBean; import org.apache.activemq.util.IntrospectionSupport; @@ -144,6 +147,49 @@ public void testAddPropertyRefFromFileAsList() throws Exception { } + @Test + public void testRemovePropertyRefNetworkConnector() throws Exception { + + System.setProperty("network.uri", "static:(tcp://localhost:8888)"); + System.setProperty("network.user", "guest"); + System.setProperty("network.password", "secret"); + + final String brokerConfig = "SpringPropertyRemoveTest-broker"; + applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property-two-nc"); + startBroker(brokerConfig); + assertTrue("broker alive", brokerService.isStarted()); + assertEquals("two network connectors", 2, brokerService.getNetworkConnectors().size()); + + for (DiscoveryNetworkConnector nc : asDiscoveryConnectors(brokerService.getNetworkConnectors())) { + assertEquals("uri resolved", System.getProperty("network.uri"), nc.getUri().toASCIIString()); + assertEquals("userName resolved", System.getProperty("network.user"), nc.getUserName()); + assertEquals("password resolved", System.getProperty("network.password"), nc.getPassword()); + } + + applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property-one-nc", SLEEP); + + assertTrue("one network connector remains", Wait.waitFor(new Wait.Condition() { + @Override + public boolean isSatisified() throws Exception { + return 1 == brokerService.getNetworkConnectors().size(); + } + })); + + DiscoveryNetworkConnector remaining = (DiscoveryNetworkConnector) brokerService.getNetworkConnectors().get(0); + assertEquals("kept the one named 'one'", "one", remaining.getName()); + assertEquals("uri still resolved", System.getProperty("network.uri"), remaining.getUri().toASCIIString()); + assertEquals("userName still resolved", System.getProperty("network.user"), remaining.getUserName()); + assertEquals("password still resolved", System.getProperty("network.password"), remaining.getPassword()); + } + + private static List asDiscoveryConnectors(List connectors) { + List result = new ArrayList<>(connectors.size()); + for (NetworkConnector nc : connectors) { + result.add((DiscoveryNetworkConnector) nc); + } + return result; + } + @Test public void testAddPropertyRefFromFileAndBeanFactory() throws Exception { diff --git a/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-one-nc.xml b/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-one-nc.xml new file mode 100644 index 00000000000..f6245e826a5 --- /dev/null +++ b/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-one-nc.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + diff --git a/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-two-nc.xml b/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-two-nc.xml new file mode 100644 index 00000000000..2900c508607 --- /dev/null +++ b/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyUpdatableConfig1000-spring-property-two-nc.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + +