From 3ae0c100a0241be9f4aaa950f61b5af8bfe98246 Mon Sep 17 00:00:00 2001 From: David Gammon Date: Fri, 17 Oct 2025 11:35:24 +0100 Subject: [PATCH 1/3] Adding support for list access using env variables --- .../env/EnvironmentPropertySource.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java b/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java index 6f5464a4eea..75db474ffdd 100644 --- a/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java +++ b/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java @@ -28,6 +28,10 @@ * @since 1.0 */ public class EnvironmentPropertySource extends MapPropertySource { + /** + * Converts list elemtents defined as _0 or _0_ into names that the resolver can understand; i.e., [0]. + */ + private static final String LIST_CONVERTER_REGEX = "_([0-9]{1,2})(?:_|$)"; /** * The position of the loader. @@ -77,20 +81,20 @@ static Map getEnv(@Nullable List includes, @Nullable List exclud } static Map getEnv(Map env, @Nullable List includes, @Nullable List excludes) { - if (includes != null || excludes != null) { - Map result = new HashMap<>(); - for (Map.Entry entry : env.entrySet()) { - String envVar = entry.getKey(); - if (excludes != null && excludes.contains(envVar)) { - continue; - } - if (includes != null && !includes.contains(envVar)) { - continue; - } - result.put(envVar, entry.getValue()); + Map result = new HashMap<>(); + for (Map.Entry entry : env.entrySet()) { + String envVar = entry.getKey(); + if (excludes != null && excludes.contains(envVar)) { + continue; + } + if (includes != null && !includes.contains(envVar)) { + continue; } - return result; + + String convertedEnvVar = envVar.replaceAll(LIST_CONVERTER_REGEX, "[$1]"); + + result.put(convertedEnvVar, entry.getValue()); } - return env; + return result; } } From 97c314bf4483123281596637ec96b3c95a5a700f Mon Sep 17 00:00:00 2001 From: David Gammon Date: Mon, 20 Oct 2025 08:19:23 +0100 Subject: [PATCH 2/3] Adding tests --- .../env/EnvironmentPropertySourceSpec.groovy | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy b/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy index 642a2dc5002..b0a29502475 100644 --- a/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy +++ b/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy @@ -88,5 +88,25 @@ class EnvironmentPropertySourceSpec extends Specification { cleanup: context.close() } - + + void "test environment variable list conversion scenarios"() { + def envs = SystemLambda.withEnvironmentVariable("A_0", "valueA") + .and("A_0__B", "nestedValueB") + .and("A_0__C_0", "multipleArraysC") + + ApplicationContext context = envs.execute(() -> ApplicationContext.builder().start()) + + expect: + context.getProperty("a[0]", String).isPresent() + context.getRequiredProperty("a[0]", String) == "valueA" + + context.getProperty("a[0].b", String).isPresent() + context.getRequiredProperty("a[0].b", String) == "nestedValueB" + + context.getProperty("a[0].c[0]", String).isPresent() + context.getRequiredProperty("a[0].c[0]", String) == "multipleArraysC" + + cleanup: + context.close() + } } From 41eb0c9c532c3a51d1078730ccc4c272e86acdc9 Mon Sep 17 00:00:00 2001 From: David Gammon Date: Mon, 20 Oct 2025 09:13:34 +0100 Subject: [PATCH 3/3] Code review comments --- .../context/env/EnvironmentPropertySource.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java b/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java index 75db474ffdd..8c7220ccceb 100644 --- a/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java +++ b/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java @@ -17,9 +17,10 @@ import io.micronaut.core.annotation.Nullable; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; /** * Loads properties from environment variables via {@link System#getenv()}. @@ -29,9 +30,9 @@ */ public class EnvironmentPropertySource extends MapPropertySource { /** - * Converts list elemtents defined as _0 or _0_ into names that the resolver can understand; i.e., [0]. + * Converts list elements defined as _0 or _0_ into names that the resolver can understand; i.e., [0]. */ - private static final String LIST_CONVERTER_REGEX = "_([0-9]{1,2})(?:_|$)"; + private static final Pattern LIST_CONVERTER_REGEX = Pattern.compile("_([0-9]{1,2})(?:_|$)"); /** * The position of the loader. @@ -81,7 +82,7 @@ static Map getEnv(@Nullable List includes, @Nullable List exclud } static Map getEnv(Map env, @Nullable List includes, @Nullable List excludes) { - Map result = new HashMap<>(); + Map result = new LinkedHashMap<>(); for (Map.Entry entry : env.entrySet()) { String envVar = entry.getKey(); if (excludes != null && excludes.contains(envVar)) { @@ -91,10 +92,11 @@ static Map getEnv(Map env, @Nullable List includes, @Nul continue; } - String convertedEnvVar = envVar.replaceAll(LIST_CONVERTER_REGEX, "[$1]"); + String convertedEnvVar = LIST_CONVERTER_REGEX.matcher(envVar).replaceAll("[$1]"); result.put(convertedEnvVar, entry.getValue()); } + return result; } }