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

zrlw pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.3 by this push:
     new b16c837be7 Fix UnsupportedOperationException in 
DubboDefaultPropertiesEnvironmentPostProcessor on immutable defaultProperties 
(#16268) (#16313)
b16c837be7 is described below

commit b16c837be7203b9d1c320799a1857ec530c8a29b
Author: Jason <[email protected]>
AuthorDate: Wed Jun 24 05:03:38 2026 -0400

    Fix UnsupportedOperationException in 
DubboDefaultPropertiesEnvironmentPostProcessor on immutable defaultProperties 
(#16268) (#16313)
---
 ...oDefaultPropertiesEnvironmentPostProcessor.java | 10 +++++--
 ...aultPropertiesEnvironmentPostProcessorTest.java | 34 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git 
a/dubbo-spring-boot-project/dubbo-spring-boot/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java
 
b/dubbo-spring-boot-project/dubbo-spring-boot/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java
index c2180f6a48..3712cc0cff 100644
--- 
a/dubbo-spring-boot-project/dubbo-spring-boot/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java
+++ 
b/dubbo-spring-boot-project/dubbo-spring-boot/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java
@@ -127,13 +127,17 @@ public class 
DubboDefaultPropertiesEnvironmentPostProcessor implements Environme
         if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
             PropertySource<?> source = 
propertySources.get(PROPERTY_SOURCE_NAME);
             if (source instanceof MapPropertySource) {
-                target = (MapPropertySource) source;
+                // The existing backing map may be immutable, so copy into a 
mutable map and replace the
+                // source instead of mutating it in place. See dubbo#16268.
+                Map<String, Object> merged = new 
HashMap<>(((MapPropertySource) source).getSource());
                 for (Map.Entry<String, Object> entry : map.entrySet()) {
                     String key = entry.getKey();
-                    if (!target.containsProperty(key)) {
-                        target.getSource().put(key, entry.getValue());
+                    if (!merged.containsKey(key)) {
+                        merged.put(key, entry.getValue());
                     }
                 }
+                target = new MapPropertySource(PROPERTY_SOURCE_NAME, merged);
+                propertySources.replace(PROPERTY_SOURCE_NAME, target);
             }
         }
         if (target == null) {
diff --git 
a/dubbo-spring-boot-project/dubbo-spring-boot/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java
 
b/dubbo-spring-boot-project/dubbo-spring-boot/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java
index 06e4625d6a..2dfa5ffcec 100644
--- 
a/dubbo-spring-boot-project/dubbo-spring-boot/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java
+++ 
b/dubbo-spring-boot-project/dubbo-spring-boot/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java
@@ -16,7 +16,9 @@
  */
 package org.apache.dubbo.spring.boot.env;
 
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.Map;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.SpringApplication;
@@ -26,6 +28,7 @@ import org.springframework.core.env.MutablePropertySources;
 import org.springframework.core.env.PropertySource;
 import org.springframework.mock.env.MockEnvironment;
 
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
@@ -106,4 +109,35 @@ class DubboDefaultPropertiesEnvironmentPostProcessorTest {
         assertNotNull(defaultPropertySource);
         assertEquals("virtual", 
defaultPropertySource.getProperty("dubbo.protocol.threadpool"));
     }
+
+    /** #16268: addOrReplace must not fail when "defaultProperties" is backed 
by an immutable map. */
+    @Test
+    void testPostProcessEnvironmentOnImmutableDefaultProperties() {
+        MockEnvironment environment = new MockEnvironment();
+        MutablePropertySources propertySources = 
environment.getPropertySources();
+        propertySources.addLast(
+                new MapPropertySource("defaultProperties", 
Collections.unmodifiableMap(new HashMap<String, Object>())));
+
+        instance.postProcessEnvironment(environment, springApplication);
+
+        PropertySource<?> defaultPropertySource = 
propertySources.get("defaultProperties");
+        assertNotNull(defaultPropertySource);
+        assertEquals("true", 
defaultPropertySource.getProperty("dubbo.config.multiple"));
+    }
+
+    /** #16268: on an immutable "defaultProperties", Dubbo's default must not 
override an existing key. */
+    @Test
+    void testImmutableDefaultPropertiesDoesNotOverrideExistingKey() {
+        MockEnvironment environment = new MockEnvironment();
+        MutablePropertySources propertySources = 
environment.getPropertySources();
+        Map<String, Object> existing = new HashMap<>();
+        existing.put("dubbo.config.multiple", "false");
+        propertySources.addLast(new MapPropertySource("defaultProperties", 
Collections.unmodifiableMap(existing)));
+
+        assertDoesNotThrow(() -> instance.postProcessEnvironment(environment, 
springApplication));
+
+        PropertySource<?> defaultPropertySource = 
propertySources.get("defaultProperties");
+        assertNotNull(defaultPropertySource);
+        assertEquals("false", 
defaultPropertySource.getProperty("dubbo.config.multiple"));
+    }
 }

Reply via email to