You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/04/20 02:44:58 UTC

[incubator-servicecomb-java-chassis] 01/02: SCB-453 read config from application.yml/application.properties

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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git

commit c760b1c9e94b6a167990f28f5b1da126d0ad5221
Author: yaohaishi <ya...@huawei.com>
AuthorDate: Thu Apr 19 19:40:24 2018 +0800

    SCB-453 read config from application.yml/application.properties
---
 .../org/apache/servicecomb/config/ConfigUtil.java  |  28 +++-
 .../config/ConfigurationSpringInitializer.java     |  92 ++++++++++-
 .../apache/servicecomb/config/TestConfigUtil.java  |  85 ++++++----
 .../config/TestConfigurationSpringInitializer.java | 172 ++++++++++++++++++++-
 4 files changed, 334 insertions(+), 43 deletions(-)

diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java
index 076caaf..a5ff2e6 100644
--- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java
+++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java
@@ -23,6 +23,7 @@ import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants
 
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -55,6 +56,16 @@ public final class ConfigUtil {
 
   private static Map<String, Object> localConfig = new HashMap<>();
 
+  /**
+   * <p>The configurations not read by ServiceComb.</p>
+   * <p>
+   * For example, this map can store the configurations read by SpringBoot from application.properties,
+   * If users write the configurations of ServiceComb into application.yml instead of microservice.yaml,
+   * this can help {@link ConfigUtil} load config correctly.
+   * </p>
+   */
+  private static final Map<String, Map<String, Object>> EXTRA_CONFIG_MAP = new LinkedHashMap<>();
+
   private ConfigUtil() {
   }
 
@@ -110,8 +121,6 @@ public final class ConfigUtil {
     return config;
   }
 
-
-
   public static ConcurrentCompositeConfiguration createLocalConfig(List<ConfigModel> configModelList) {
     ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration();
 
@@ -125,6 +134,13 @@ public final class ConfigUtil {
         new DynamicConfiguration(
             new MicroserviceConfigurationSource(configModelList), new NeverStartPollingScheduler()),
         "configFromYamlFile");
+    // If there is extra configurations, add it into config. Extra config has lowest priority.
+    EXTRA_CONFIG_MAP.entrySet().stream()
+        .filter(mapEntry -> !mapEntry.getValue().isEmpty())
+        .forEachOrdered(configMapEntry ->
+            duplicateServiceCombConfigToCse(config,
+                new ConcurrentMapConfiguration(configMapEntry.getValue()),
+                configMapEntry.getKey()));
 
     return config;
   }
@@ -210,6 +226,14 @@ public final class ConfigUtil {
     ConfigurationManager.install(dynamicConfig);
   }
 
+  public static void addExtraConfig(String extraConfigName, Map<String, Object> extraConfig) {
+    EXTRA_CONFIG_MAP.put(extraConfigName, extraConfig);
+  }
+
+  public static void clearExtraConfig() {
+    EXTRA_CONFIG_MAP.clear();
+  }
+
   private static class ServiceCombPropertyUpdateListener implements WatchedUpdateListener {
 
     private final ConcurrentMapConfiguration injectConfig;
diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationSpringInitializer.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationSpringInitializer.java
index 05b85cf..0288d93 100644
--- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationSpringInitializer.java
+++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationSpringInitializer.java
@@ -18,23 +18,53 @@
 package org.apache.servicecomb.config;
 
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Properties;
 
 import org.apache.commons.configuration.AbstractConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.EnvironmentAware;
 import org.springframework.core.Ordered;
+import org.springframework.core.env.CompositePropertySource;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.PropertySource;
+import org.springframework.util.StringUtils;
 
 import com.netflix.config.ConfigurationManager;
 import com.netflix.config.DynamicPropertyFactory;
 
-public class ConfigurationSpringInitializer extends PropertyPlaceholderConfigurer {
+public class ConfigurationSpringInitializer extends PropertyPlaceholderConfigurer implements EnvironmentAware {
+  private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationSpringInitializer.class);
+
+  public static final String EXTRA_CONFIG_SOURCE_PREFIX = "extraConfig-";
+
   public ConfigurationSpringInitializer() {
-    ConfigUtil.installDynamicConfig();
     setOrder(Ordered.LOWEST_PRECEDENCE / 2);
     setIgnoreUnresolvablePlaceholders(true);
   }
 
+  /**
+   * Get configurations from Spring, merge them into the configurations of ServiceComb.
+   * @param environment From which to get the extra config.
+   */
+  @Override
+  public void setEnvironment(Environment environment) {
+    String environmentName = generateNameForEnvironment(environment);
+    LOGGER.info("Environment received, will get configurations from [{}].", environmentName);
+
+    Map<String, Object> extraConfig = getAllProperties(environment);
+
+    ConfigUtil.addExtraConfig(EXTRA_CONFIG_SOURCE_PREFIX + environmentName, extraConfig);
+
+    ConfigUtil.installDynamicConfig();
+  }
+
   @Override
   protected Properties mergeProperties() throws IOException {
     Properties properties = super.mergeProperties();
@@ -57,4 +87,62 @@ public class ConfigurationSpringInitializer extends PropertyPlaceholderConfigure
     }
     return propertyValue;
   }
+
+  /**
+   * Try to get a name for identifying the environment.
+   * @param environment the target that the name is generated for.
+   * @return The generated name for the environment.
+   */
+  private String generateNameForEnvironment(Environment environment) {
+    String environmentName = environment.getProperty("spring.config.name");
+    if (!StringUtils.isEmpty(environmentName)) {
+      return environmentName;
+    }
+
+    environmentName = environment.getProperty("spring.application.name");
+    if (!StringUtils.isEmpty(environmentName)) {
+      return environmentName;
+    }
+
+    return environment.getClass().getName() + "@" + environment.hashCode();
+  }
+
+  /**
+   * Traversal all {@link PropertySource} of {@link ConfigurableEnvironment}, and try to get all properties.
+   */
+  private Map<String, Object> getAllProperties(Environment environment) {
+    Map<String, Object> configFromSpringBoot = new HashMap<>();
+
+    if (!(environment instanceof ConfigurableEnvironment)) {
+      return configFromSpringBoot;
+    }
+
+    ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment;
+    for (PropertySource<?> propertySource : configurableEnvironment.getPropertySources()) {
+      getProperties(configurableEnvironment, propertySource, configFromSpringBoot);
+    }
+    return configFromSpringBoot;
+  }
+
+  /**
+   * Get property names from {@link EnumerablePropertySource}, and get property value from {@link ConfigurableEnvironment#getProperty(String)}
+   */
+  private void getProperties(ConfigurableEnvironment environment, PropertySource<?> propertySource,
+      Map<String, Object> configFromSpringBoot) {
+    if (propertySource instanceof CompositePropertySource) {
+      // recursively get EnumerablePropertySource
+      CompositePropertySource compositePropertySource = (CompositePropertySource) propertySource;
+      compositePropertySource.getPropertySources().forEach(ps -> getProperties(environment, ps, configFromSpringBoot));
+      return;
+    }
+    if (propertySource instanceof EnumerablePropertySource) {
+      EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) propertySource;
+      for (String propertyName : enumerablePropertySource.getPropertyNames()) {
+        configFromSpringBoot.put(propertyName, environment.getProperty(propertyName));
+      }
+      return;
+    }
+
+    LOGGER.debug("a none EnumerablePropertySource is ignored, propertySourceName = [{}]", propertySource.getName());
+  }
 }
diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java
index a61555a..b10142d 100644
--- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java
+++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java
@@ -25,16 +25,16 @@ import static org.junit.Assert.assertThat;
 import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.HashMap;
 
-import com.netflix.config.*;
 import org.apache.commons.configuration.AbstractConfiguration;
 import org.apache.commons.configuration.Configuration;
 import org.apache.servicecomb.config.archaius.sources.ConfigModel;
 import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
 import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.junit.AfterClass;
@@ -42,6 +42,11 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.DynamicConfiguration;
+import com.netflix.config.DynamicPropertyFactory;
+import com.netflix.config.DynamicWatchedConfiguration;
+
 import mockit.Deencapsulation;
 import mockit.Expectations;
 import mockit.Mocked;
@@ -73,13 +78,13 @@ public class TestConfigUtil {
   }
 
   @AfterClass
-  public static void tearDown() throws Exception {
+  public static void tearDown() {
     ArchaiusUtils.resetConfig();
   }
 
   @Test
   public void testAddConfig() {
-    Map config = new HashMap<String, Object>();
+    Map<String, Object> config = new HashMap<>();
     config.put("service_description.name", "service_name_test");
     ConfigUtil.setConfigs(config);
     ConfigUtil.addConfig("service_description.version", "1.0.2");
@@ -87,7 +92,7 @@ public class TestConfigUtil {
     ConfigUtil.addConfig("cse.test.num", 10);
     AbstractConfiguration configuration = ConfigUtil.createDynamicConfig();
     Assert.assertEquals(configuration.getString("service_description.name"), "service_name_test");
-    Assert.assertEquals(configuration.getBoolean("cse.test.enabled"), true);
+    Assert.assertTrue(configuration.getBoolean("cse.test.enabled"));
     Assert.assertEquals(configuration.getInt("cse.test.num"), 10);
   }
 
@@ -116,8 +121,7 @@ public class TestConfigUtil {
   }
 
   @Test
-  public void testCreateDynamicConfigHasConfigCenter(
-      @Mocked ConfigCenterConfigurationSource configCenterConfigurationSource) {
+  public void testCreateDynamicConfigHasConfigCenter() {
     AbstractConfiguration dynamicConfig = ConfigUtil.createDynamicConfig();
     Assert.assertEquals(DynamicWatchedConfiguration.class,
         ((ConcurrentCompositeConfiguration) dynamicConfig).getConfiguration(0).getClass());
@@ -130,54 +134,54 @@ public class TestConfigUtil {
   }
 
   @Test
-  public void propertiesFromFileIsDuplicatedToCse() throws Exception {
+  public void propertiesFromFileIsDuplicatedToCse() {
     String expected = "value";
 
     assertThat(DynamicPropertyFactory
-        .getInstance()
-        .getStringProperty("servicecomb.cse.servicecomb.file", null)
-        .get(),
+            .getInstance()
+            .getStringProperty("servicecomb.cse.servicecomb.file", null)
+            .get(),
         equalTo(expected));
 
     assertThat(DynamicPropertyFactory
-        .getInstance()
-        .getStringProperty("cse.cse.servicecomb.file", null)
-        .get(),
+            .getInstance()
+            .getStringProperty("cse.cse.servicecomb.file", null)
+            .get(),
         equalTo(expected));
   }
 
   @Test
-  public void propertiesFromSystemIsDuplicatedToCse() throws Exception {
+  public void propertiesFromSystemIsDuplicatedToCse() {
     assertThat(DynamicPropertyFactory
-        .getInstance()
-        .getStringProperty(systemPropertyName, null)
-        .get(),
+            .getInstance()
+            .getStringProperty(systemPropertyName, null)
+            .get(),
         equalTo(systemExpected));
 
     assertThat(DynamicPropertyFactory
-        .getInstance()
-        .getStringProperty("servicecomb.cse.servicecomb.system.setting", null)
-        .get(),
+            .getInstance()
+            .getStringProperty("servicecomb.cse.servicecomb.system.setting", null)
+            .get(),
         equalTo(systemExpected));
   }
 
   @Test
-  public void propertiesFromEnvironmentIsDuplicatedToCse() throws Exception {
+  public void propertiesFromEnvironmentIsDuplicatedToCse() {
     assertThat(DynamicPropertyFactory
-        .getInstance()
-        .getStringProperty(environmentPropertyName, null)
-        .get(),
+            .getInstance()
+            .getStringProperty(environmentPropertyName, null)
+            .get(),
         equalTo(environmentExpected));
 
     assertThat(DynamicPropertyFactory
-        .getInstance()
-        .getStringProperty("servicecomb.cse.servicecomb.environment.setting", null)
-        .get(),
+            .getInstance()
+            .getStringProperty("servicecomb.cse.servicecomb.environment.setting", null)
+            .get(),
         equalTo(environmentExpected));
   }
 
   @Test
-  public void duplicateServiceCombConfigToCseListValue() throws Exception {
+  public void duplicateServiceCombConfigToCseListValue() {
     List<String> list = Arrays.asList("a", "b");
 
     AbstractConfiguration config = new DynamicConfiguration();
@@ -190,7 +194,7 @@ public class TestConfigUtil {
   }
 
   @Test
-  public void propertiesAddFromDynamicConfigSourceIsDuplicated() throws Exception {
+  public void propertiesAddFromDynamicConfigSourceIsDuplicated() {
     String expected = uniquify("ran");
     String someProperty = "servicecomb.cse.servicecomb.add";
     String injectProperty = "cse.cse.servicecomb.add";
@@ -231,7 +235,7 @@ public class TestConfigUtil {
   }
 
   @Test
-  public void propertiesChangeFromDynamicConfigSourceIsDuplicated() throws Exception {
+  public void propertiesChangeFromDynamicConfigSourceIsDuplicated() {
     String expected = uniquify("ran");
     String someProperty = "servicecomb.cse.servicecomb.change";
     String injectProperty = "cse.cse.servicecomb.change";
@@ -269,7 +273,7 @@ public class TestConfigUtil {
   }
 
   @Test
-  public void propertiesDeleteFromDynamicConfigSourceIsDuplicated() throws Exception {
+  public void propertiesDeleteFromDynamicConfigSourceIsDuplicated() {
     String expected = uniquify("ran");
     String someProperty = "servicecomb.cse.servicecomb.delete";
     String injectProperty = "cse.cse.servicecomb.delete";
@@ -315,6 +319,23 @@ public class TestConfigUtil {
     assertThat(result.getString("cse_service_registry_address"), equalTo("testing"));
   }
 
+  @Test
+  public void testCreateLocalConfigWithExtraConfig() {
+    Map<String, Object> extraConfig = new ConcurrentHashMapEx<>(1);
+    String extraConfigKey = "extraConfigKey";
+    String extraConfigValue = "value";
+    String overriddenConfigKey = "servicecomb.cse.servicecomb.file";
+    extraConfig.put(extraConfigKey, extraConfigValue);
+    extraConfig.put(overriddenConfigKey, "should_be_overridden");
+
+    ConfigUtil.addExtraConfig("testExtraConfig", extraConfig);
+
+    ConcurrentCompositeConfiguration localConfiguration = ConfigUtil.createLocalConfig();
+
+    Assert.assertEquals(extraConfigValue, localConfiguration.getProperty(extraConfigKey));
+    Assert.assertEquals("value", localConfiguration.getString(overriddenConfigKey));
+  }
+
   @SuppressWarnings("unchecked")
   private static void setEnv(String key, String value) throws IllegalAccessException, NoSuchFieldException {
     Class<?>[] classes = Collections.class.getDeclaredClasses();
diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigurationSpringInitializer.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigurationSpringInitializer.java
index b2c5da0..3dc9b71 100644
--- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigurationSpringInitializer.java
+++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigurationSpringInitializer.java
@@ -16,36 +16,54 @@
  */
 package org.apache.servicecomb.config;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyString;
+
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.commons.configuration.Configuration;
 import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
-import org.junit.AfterClass;
+import org.junit.After;
 import org.junit.Assert;
-import org.junit.BeforeClass;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
 import org.springframework.core.Ordered;
+import org.springframework.core.env.CompositePropertySource;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.jndi.JndiPropertySource;
 
 import com.netflix.config.ConfigurationManager;
 
 import mockit.Deencapsulation;
 
 public class TestConfigurationSpringInitializer {
-  @BeforeClass
-  public static void classSetup() {
+  @Before
+  public void beforeTest() {
+    ConfigUtil.clearExtraConfig();
     ArchaiusUtils.resetConfig();
   }
 
-  @AfterClass
-  public static void classTeardown() {
+  @After
+  public void afterTest() {
+    ConfigUtil.clearExtraConfig();
     ArchaiusUtils.resetConfig();
   }
 
   @Test
   public void testAll() {
     ConfigurationSpringInitializer configurationSpringInitializer = new ConfigurationSpringInitializer();
+    ConfigUtil.installDynamicConfig();
 
     Assert.assertEquals(Ordered.LOWEST_PRECEDENCE / 2, configurationSpringInitializer.getOrder());
     Assert.assertEquals(true,
@@ -55,7 +73,7 @@ public class TestConfigurationSpringInitializer {
     @SuppressWarnings("unchecked")
     List<Map<String, Object>> listO = (List<Map<String, Object>>) o;
     Assert.assertEquals(3, listO.size());
-    Assert.assertEquals(null, ConfigUtil.getProperty("notExist"));
+    Assert.assertNull(ConfigUtil.getProperty("notExist"));
 
     MicroserviceConfigLoader loader = ConfigUtil.getMicroserviceConfigLoader();
     Assert.assertNotNull(loader);
@@ -65,4 +83,144 @@ public class TestConfigurationSpringInitializer {
     // must not reinstall
     Assert.assertEquals(instance, ConfigurationManager.getConfigInstance());
   }
+
+  @Test
+  public void testSetEnvironment() {
+    ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class);
+    MutablePropertySources propertySources = new MutablePropertySources();
+    Map<String, String> propertyMap = new HashMap<>();
+    final String map0Key0 = "map0-Key0";
+    final String map1Key0 = "map1-Key0";
+    final String map2Key0 = "map2-Key0";
+    final String map3Key0 = "map3-Key0";
+    propertyMap.put(map0Key0, "map0-Value0");
+    propertyMap.put(map1Key0, "map1-Value0");
+    propertyMap.put(map2Key0, "map2-Value0");
+    propertyMap.put(map3Key0, "map3-Value0");
+
+    /*
+    propertySources
+    |- compositePropertySource0
+    |  |- mapPropertySource0
+    |  |  |- map0-Key0 = map0-Value0
+    |  |- compositePropertySource1
+    |     |- mapPropertySource1
+    |     |  |- map1-Key0 = map1-Value0
+    |     |- mapPropertySource2
+    |        |- map2-Key0 = map2-Value0
+    |     |- JndiPropertySource(mocked)
+    |- mapPropertySource3
+      |- map3-Key0 = map3-Value0
+     */
+    CompositePropertySource compositePropertySource0 = new CompositePropertySource("compositePropertySource0");
+    propertySources.addFirst(compositePropertySource0);
+
+    HashMap<String, Object> map0 = new HashMap<>();
+    map0.put(map0Key0, propertyMap.get(map0Key0));
+    MapPropertySource mapPropertySource0 = new MapPropertySource("mapPropertySource0", map0);
+    compositePropertySource0.addFirstPropertySource(mapPropertySource0);
+
+    CompositePropertySource compositePropertySource1 = new CompositePropertySource("compositePropertySource1");
+    compositePropertySource0.addPropertySource(compositePropertySource1);
+    HashMap<String, Object> map1 = new HashMap<>();
+    map1.put(map1Key0, propertyMap.get(map1Key0));
+    MapPropertySource mapPropertySource1 = new MapPropertySource("mapPropertySource1", map1);
+    compositePropertySource1.addPropertySource(mapPropertySource1);
+    HashMap<String, Object> map2 = new HashMap<>();
+    map2.put(map2Key0, propertyMap.get(map2Key0));
+    MapPropertySource mapPropertySource2 = new MapPropertySource("mapPropertySource2", map2);
+    compositePropertySource1.addPropertySource(mapPropertySource2);
+    compositePropertySource1.addPropertySource(Mockito.mock(JndiPropertySource.class));
+
+    HashMap<String, Object> map3 = new HashMap<>();
+    map3.put(map3Key0, propertyMap.get(map3Key0));
+    MapPropertySource mapPropertySource3 = new MapPropertySource("mapPropertySource3", map3);
+    compositePropertySource0.addPropertySource(mapPropertySource3);
+
+    Mockito.when(environment.getPropertySources()).thenReturn(propertySources);
+    Mockito.doAnswer((Answer<String>) invocation -> {
+      Object[] args = invocation.getArguments();
+      String propertyName = (String) args[0];
+
+      if ("spring.config.name".equals(propertyName) || "spring.application.name".equals(propertyName)) {
+        return null;
+      }
+
+      String value = propertyMap.get(propertyName);
+      if (null == value) {
+        fail("get unexpected property name: " + propertyName);
+      }
+      return value;
+    }).when(environment).getProperty(anyString());
+
+    new ConfigurationSpringInitializer().setEnvironment(environment);
+
+    Map<String, Map<String, Object>> extraLocalConfig = getExtraConfigMapFromConfigUtil();
+    assertFalse(extraLocalConfig.isEmpty());
+    Map<String, Object> extraProperties = extraLocalConfig
+        .get(ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + environment.getClass().getName() + "@"
+            + environment.hashCode());
+    assertNotNull(extraLocalConfig);
+    for (Entry<String, String> entry : propertyMap.entrySet()) {
+      assertEquals(entry.getValue(), extraProperties.get(entry.getKey()));
+    }
+  }
+
+  @Test
+  public void testSetEnvironmentOnEnvironmentName() {
+    // get environment name from spring.config.name
+    ConfigurableEnvironment environment0 = Mockito.mock(ConfigurableEnvironment.class);
+    MutablePropertySources propertySources0 = new MutablePropertySources();
+    Mockito.when(environment0.getPropertySources()).thenReturn(propertySources0);
+    Map<String, Object> map0 = new HashMap<>(1);
+    map0.put("spring.config.name", "application");
+    propertySources0.addFirst(new MapPropertySource("mapPropertySource0", map0));
+    Mockito.when(environment0.getProperty("spring.config.name")).thenReturn("application");
+
+    // get environment name from spring.application.name
+    ConfigurableEnvironment environment1 = Mockito.mock(ConfigurableEnvironment.class);
+    MutablePropertySources propertySources1 = new MutablePropertySources();
+    Mockito.when(environment1.getPropertySources()).thenReturn(propertySources1);
+    Map<String, Object> map1 = new HashMap<>(1);
+    map1.put("spring.application.name", "bootstrap");
+    propertySources1.addFirst(new MapPropertySource("mapPropertySource1", map1));
+    Mockito.when(environment1.getProperty("spring.application.name")).thenReturn("bootstrap");
+
+    // get environment name from className+hashcode
+    ConfigurableEnvironment environment2 = Mockito.mock(ConfigurableEnvironment.class);
+    MutablePropertySources propertySources2 = new MutablePropertySources();
+    Mockito.when(environment2.getPropertySources()).thenReturn(propertySources2);
+    Map<String, Object> map2 = new HashMap<>(1);
+    map2.put("key2", "value2");
+    propertySources2.addFirst(new MapPropertySource("mapPropertySource2", map2));
+    Mockito.when(environment2.getProperty("key2")).thenReturn("value2");
+
+    ConfigurationSpringInitializer configurationSpringInitializer = new ConfigurationSpringInitializer();
+    configurationSpringInitializer.setEnvironment(environment0);
+    configurationSpringInitializer.setEnvironment(environment1);
+    configurationSpringInitializer.setEnvironment(environment2);
+
+    Map<String, Map<String, Object>> extraConfig = getExtraConfigMapFromConfigUtil();
+    assertEquals(3, extraConfig.size());
+
+    Map<String, Object> extraProperties = extraConfig
+        .get(ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + "application");
+    assertEquals(1, extraProperties.size());
+    assertEquals("application", extraProperties.get("spring.config.name"));
+
+    extraProperties = extraConfig.get(ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + "bootstrap");
+    assertEquals(1, extraProperties.size());
+    assertEquals("bootstrap", extraProperties.get("spring.application.name"));
+
+    extraProperties = extraConfig.get(
+        ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + environment2.getClass().getName() + "@"
+            + environment2.hashCode());
+    assertEquals(1, extraProperties.size());
+    assertEquals("value2", extraProperties.get("key2"));
+  }
+
+  private Map<String, Map<String, Object>> getExtraConfigMapFromConfigUtil() {
+    return Deencapsulation
+        .getField(ConfigUtil.class, "EXTRA_CONFIG_MAP");
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.