From 7b48d82605bb3c019d1391bd7091463fcd25b92c Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Sat, 9 Mar 2024 11:49:40 +0000 Subject: [PATCH] Improve relocates and fallbacks --- .../FallbackConfigSourceInterceptor.java | 10 +- .../RelocateConfigSourceInterceptor.java | 10 +- .../io/smallrye/config/SmallRyeConfig.java | 17 ++- .../RelocateConfigSourceInterceptorTest.java | 106 +++++++++++++++++- 4 files changed, 126 insertions(+), 17 deletions(-) diff --git a/implementation/src/main/java/io/smallrye/config/FallbackConfigSourceInterceptor.java b/implementation/src/main/java/io/smallrye/config/FallbackConfigSourceInterceptor.java index 0043da22b..5c6babb6d 100644 --- a/implementation/src/main/java/io/smallrye/config/FallbackConfigSourceInterceptor.java +++ b/implementation/src/main/java/io/smallrye/config/FallbackConfigSourceInterceptor.java @@ -31,9 +31,15 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final ConfigValue fallbackValue = context.proceed(map); // Check which one comes from a higher ordinal source if (configValue != null && fallbackValue != null) { - return CONFIG_SOURCE_COMPARATOR.compare(configValue, fallbackValue) >= 0 ? configValue : fallbackValue; + return CONFIG_SOURCE_COMPARATOR.compare(configValue, fallbackValue) >= 0 ? configValue + : fallbackValue.withName(name); } else { - return configValue != null ? configValue : fallbackValue; + if (configValue != null) { + return configValue; + } else if (fallbackValue != null) { + return fallbackValue.withName(name); + } + return null; } } } diff --git a/implementation/src/main/java/io/smallrye/config/RelocateConfigSourceInterceptor.java b/implementation/src/main/java/io/smallrye/config/RelocateConfigSourceInterceptor.java index bc7b23adf..2c5927dd6 100644 --- a/implementation/src/main/java/io/smallrye/config/RelocateConfigSourceInterceptor.java +++ b/implementation/src/main/java/io/smallrye/config/RelocateConfigSourceInterceptor.java @@ -31,9 +31,15 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final ConfigValue configValue = context.proceed(name); // Check which one comes from a higher ordinal source if (relocateValue != null && configValue != null) { - return CONFIG_SOURCE_COMPARATOR.compare(relocateValue, configValue) >= 0 ? relocateValue : configValue; + return CONFIG_SOURCE_COMPARATOR.compare(relocateValue, configValue) >= 0 ? relocateValue + : configValue.withName(map); } else { - return relocateValue != null ? relocateValue : configValue; + if (relocateValue != null) { + return relocateValue; + } else if (configValue != null) { + return configValue.withName(map); + } + return null; } } } diff --git a/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java b/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java index cb4333e14..5a2e8a05e 100644 --- a/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java +++ b/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java @@ -566,7 +566,7 @@ public Iterable getPropertyNames() { */ @Experimental("Retrieve an updated list of all configuration property names") public Iterable getLatestPropertyNames() { - return configSources.getPropertyNames().get(true); + return configSources.getPropertyNames().latest(); } /** @@ -913,19 +913,18 @@ class PropertyNames implements Serializable { Iterable get() { if (names.isEmpty()) { - return get(true); + return latest(); } return names; } - Iterable get(boolean latest) { - if (latest) { - names.clear(); - Iterator namesIterator = interceptorChain.iterateNames(); - while (namesIterator.hasNext()) { - names.add(namesIterator.next()); - } + Iterable latest() { + names.clear(); + Iterator namesIterator = interceptorChain.iterateNames(); + while (namesIterator.hasNext()) { + names.add(namesIterator.next()); } + names.remove(ConfigSource.CONFIG_ORDINAL); return Collections.unmodifiableSet(names); } } diff --git a/implementation/src/test/java/io/smallrye/config/RelocateConfigSourceInterceptorTest.java b/implementation/src/test/java/io/smallrye/config/RelocateConfigSourceInterceptorTest.java index 82b8d088f..e82022543 100644 --- a/implementation/src/test/java/io/smallrye/config/RelocateConfigSourceInterceptorTest.java +++ b/implementation/src/test/java/io/smallrye/config/RelocateConfigSourceInterceptorTest.java @@ -1,5 +1,6 @@ package io.smallrye.config; +import static io.smallrye.config.ConfigMappings.mappedProperties; import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix; import static io.smallrye.config.KeyValuesConfigSource.config; import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE; @@ -19,6 +20,7 @@ import java.util.Optional; import java.util.OptionalInt; import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.microprofile.config.Config; import org.junit.jupiter.api.Test; @@ -59,7 +61,7 @@ void fallbackEmpty() { .withSources(config("mp.jwt.token.header", "")).build(); ConfigValue configValue = (ConfigValue) config.getConfigValue("smallrye.jwt.token.header"); - assertEquals("smallrye.jwt.token.header", configValue.getName()); + assertEquals("mp.jwt.token.header", configValue.getName()); assertEquals("Authorization", configValue.getValue()); } @@ -187,9 +189,9 @@ void fallbackPropertyNameToProfile() { ConfigValue value = config.getConfigValue("new"); assertEquals("5678", value.getValue()); - assertEquals("old", value.getName()); + assertEquals("new", value.getName()); assertEquals("dev", value.getProfile()); - assertEquals("%dev.old", value.getNameProfiled()); + assertEquals("%dev.new", value.getNameProfiled()); } @Test @@ -212,7 +214,7 @@ public Iterator iterateNames(final ConfigSourceInterceptorContext contex hierarchyCandidates.add("child." + name.substring(7)); } } - names.addAll(ConfigMappings.mappedProperties(configClassWithPrefix(Child.class), hierarchyCandidates)); + names.addAll(mappedProperties(configClassWithPrefix(Child.class), hierarchyCandidates)); return names.iterator(); } }; @@ -294,6 +296,102 @@ interface Nested { } } + @Test + void relocateMapping() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .addDefaultInterceptors() + .withInterceptors(new RelocateConfigSourceInterceptor(name -> name.replaceFirst("old", "new"))) + .withSources(config("config_ordinal", "1", + "reloc.old.value", "old", + "reloc.old.list[0]", "old", "reloc.old.list[1]", "old", + "reloc.old.map.key", "old", "reloc.old.map.old", "old")) + .withSources(config("config_ordinal", "2", + "reloc.new.value", "new", + "reloc.new.list[0]", "new", + "reloc.new.map.key", "new", "reloc.old.map.new", "new")) + .withMapping(RelocateMapping.class) + .build(); + + RelocateMapping mapping = config.getConfigMapping(RelocateMapping.class); + + assertEquals("new", mapping.value()); + // TODO - Maps and Lists are merged. Is this what we want? Related with https://github.com/quarkusio/quarkus/issues/38786 + assertEquals(2, mapping.list().size()); + assertEquals("new", mapping.list().get(0)); + assertEquals("old", mapping.list().get(1)); + assertEquals(3, mapping.map().size()); + assertEquals("new", mapping.map().get("key")); + assertEquals("new", mapping.map().get("new")); + assertEquals("old", mapping.map().get("old")); + + Set properties = stream(config.getPropertyNames().spliterator(), false).collect(Collectors.toSet()); + Set mappedProperties = mappedProperties(configClassWithPrefix(RelocateMapping.class), properties); + properties.removeAll(mappedProperties); + Set relocateProperties = new HashSet<>(); + for (String property : properties) { + if (mappedProperties.contains(property)) { + ConfigValue configValue = config.getConfigValue(property); + relocateProperties.add(configValue.getName()); + } + } + properties.removeAll(relocateProperties); + } + + @Test + void fallbackMapping() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .addDefaultInterceptors() + .withInterceptors(new RelocateConfigSourceInterceptor(name -> name.replaceFirst("old", "new"))) + .withInterceptors(new FallbackConfigSourceInterceptor(name -> name.replaceFirst("new", "old"))) + .withSources(config( + "fall.old.value", "old", + "fall.old.list[0]", "old", "fall.old.list[1]", "old", + "fall.old.map.key", "old", "fall.old.map.old", "old")) + .withMapping(FallbackMapping.class) + .build(); + + FallbackMapping mapping = config.getConfigMapping(FallbackMapping.class); + + assertEquals("old", mapping.value()); + assertEquals(2, mapping.list().size()); + assertEquals("old", mapping.list().get(0)); + assertEquals("old", mapping.list().get(1)); + assertEquals(2, mapping.map().size()); + assertEquals("old", mapping.map().get("key")); + assertEquals("old", mapping.map().get("old")); + + Set properties = stream(config.getPropertyNames().spliterator(), false).collect(Collectors.toSet()); + Set mappedProperties = mappedProperties(configClassWithPrefix(FallbackMapping.class), properties); + properties.removeAll(mappedProperties); + Set fallbackProperties = new HashSet<>(); + for (String property : properties) { + ConfigValue configValue = config.getConfigValue(property); + if (mappedProperties.contains(configValue.getName())) { + fallbackProperties.add(property); + } + } + properties.removeAll(fallbackProperties); + assertTrue(properties.isEmpty()); + } + + @ConfigMapping(prefix = "reloc.old") + interface RelocateMapping { + String value(); + + List list(); + + Map map(); + } + + @ConfigMapping(prefix = "fall.new") + interface FallbackMapping { + String value(); + + List list(); + + Map map(); + } + private static SmallRyeConfig buildConfig(String... keyValues) { return builder(Collections.emptySet(), keyValues).build(); }