Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Injection of Map from configuration now honors prefix (backport) #4659

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020 Oracle and/or its affiliates.
* Copyright (c) 2018, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -256,15 +256,23 @@ any java class (except for parameterized types)
config = ((MpConfigProviderResolver.ConfigDelegate) config).delegate();
}
String defaultValue = defaultValue(annotation);
Object value = configValue(config, fieldTypes, configKey, defaultValue);
Object value = configValue(config,
fieldTypes,
configKey,
defaultValue,
configKey.equals(fullPath.replace('$', '.')));

if (null == value) {
throw new NoSuchElementException("Cannot find value for key: " + configKey);
}
return value;
}

private Object configValue(Config config, FieldTypes fieldTypes, String configKey, String defaultValue) {
private Object configValue(Config config,
FieldTypes fieldTypes,
String configKey,
String defaultValue,
boolean defaultConfigKey) {
Class<?> type0 = fieldTypes.field0().rawType();
Class<?> type1 = fieldTypes.field1().rawType();
Class<?> type2 = fieldTypes.field2().rawType();
Expand All @@ -276,6 +284,7 @@ private Object configValue(Config config, FieldTypes fieldTypes, String configKe
// generic declaration
return parameterizedConfigValue(config,
configKey,
defaultConfigKey,
defaultValue,
type0,
type1,
Expand Down Expand Up @@ -332,6 +341,7 @@ private static <T> T convert(String key, Config config, String value, Class<T> t

private static Object parameterizedConfigValue(Config config,
String configKey,
boolean defaultConfigKey,
String defaultValue,
Class<?> rawType,
Class<?> typeArg,
Expand All @@ -343,6 +353,7 @@ private static Object parameterizedConfigValue(Config config,
return Optional
.ofNullable(parameterizedConfigValue(config,
configKey,
defaultConfigKey,
defaultValue,
typeArg,
typeArg2,
Expand All @@ -356,17 +367,23 @@ private static Object parameterizedConfigValue(Config config,
} else {
return (Supplier<?>) () -> parameterizedConfigValue(config,
configKey,
defaultConfigKey,
defaultValue,
typeArg,
typeArg2,
typeArg2);
}
} else if (Map.class.isAssignableFrom(rawType)) {
// config key we have should serve as a prefix, and the properties should have it removed
// similar to what the original io.helidon.config.Config.get(configKey).detach()
Map<String, String> result = new HashMap<>();
config.getPropertyNames()
.forEach(name -> {
// workaround for race condition (if key disappears from source after we call getPropertyNames
config.getOptionalValue(name, String.class).ifPresent(value -> result.put(name, value));
if (defaultConfigKey || name.startsWith(configKey)) {
String key = removePrefix(configKey, defaultConfigKey, name);
// workaround for race condition (if key disappears from source after we call getPropertyNames)
config.getOptionalValue(name, String.class).ifPresent(value -> result.put(key, value));
}
});
return result;
} else if (Set.class.isAssignableFrom(rawType)) {
Expand All @@ -377,6 +394,18 @@ private static Object parameterizedConfigValue(Config config,
}
}

private static String removePrefix(String prefix, boolean defaultConfigKey, String key) {
if (defaultConfigKey) {
return key;
}

String intermediate = key.substring(prefix.length());
if (intermediate.startsWith(".")) {
return intermediate.substring(1);
}
return intermediate;
}

static String[] toArray(String stringValue) {
String[] values = SPLIT_PATTERN.split(stringValue, -1);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020 Oracle and/or its affiliates.
* Copyright (c) 2019, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Map;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;
Expand All @@ -38,6 +39,7 @@
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertAll;

Expand All @@ -59,8 +61,30 @@ class MpConfigInjectionTest {
@Specific
private SubBean subBean;


@Test
void testInjectMapNoPrefix() {
Map<String, String> allProperties = bean.allProperties;
assertAll(
() -> assertThat(allProperties, hasEntry("inject.of", "of")),
() -> assertThat(allProperties, hasEntry("inject.valueOf", "valueOf")),
() -> assertThat(allProperties, hasEntry("inject.parse", "parse")),
() -> assertThat(allProperties, hasEntry("inject.ctor", "ctor"))
);
}

@Test
void testInjectMapWithPrefix() {
Map<String, String> injectProperties = bean.injectProperties;
assertAll(
() -> assertThat(injectProperties, hasEntry("of", "of")),
() -> assertThat(injectProperties, hasEntry("valueOf", "valueOf")),
() -> assertThat(injectProperties, hasEntry("parse", "parse")),
() -> assertThat(injectProperties, hasEntry("ctor", "ctor"))
);
}
@Test
public void testImplicitConversion() {
void testImplicitConversion() {
assertAll("Implicit conversion injection",
() -> assertThat("of", bean.of, is(Of.of("of"))),
() -> assertThat("valueOf", bean.valueOf, is(ValueOf.valueOf("valueOf"))),
Expand All @@ -70,7 +94,7 @@ public void testImplicitConversion() {
}

@Test
public void testImplicitConversionSubclass() {
void testImplicitConversionSubclass() {
assertAll("Implicit conversion injection",
() -> assertThat("of", subBean.of, is(Of.of("of"))),
() -> assertThat("valueOf", subBean.valueOf, is(ValueOf.valueOf("valueOf"))),
Expand All @@ -95,6 +119,14 @@ public static class Bean {
@Inject
@ConfigProperty(name = "inject.ctor")
public Ctor ctor;

@Inject
@ConfigProperty(name = "")
public Map<String, String> allProperties;

@Inject
@ConfigProperty(name = "inject")
public Map<String, String> injectProperties;
}

@Qualifier
Expand Down