Skip to content

Commit

Permalink
4.x: Meta-configuration fixes (helidon-io#9233)
Browse files Browse the repository at this point in the history
* Do not use meta configuration unless requested by user.
* Set global config from MP
* Ignore meta-config failures (and log them as warning) in SE
* Make sure we convert enums correctly

Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
  • Loading branch information
tomas-langer authored Sep 5, 2024
1 parent e31d55a commit 2397b81
Show file tree
Hide file tree
Showing 20 changed files with 554 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
Expand Down Expand Up @@ -452,7 +453,11 @@ private <T> Optional<Converter<T>> findImplicit(Class<T> type) {
if (Enum.class.isAssignableFrom(type)) {
return Optional.of(value -> {
Class<? extends Enum> enumClass = (Class<? extends Enum>) type;
return (T) Enum.valueOf(enumClass, value);
try {
return (T) Enum.valueOf(enumClass, value);
} catch (Exception e) {
return (T) Enum.valueOf(enumClass, value.toUpperCase(Locale.ROOT));
}
});
}
// any class that has a "public static T method()"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
* Copyright (c) 2019, 2024 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 @@ -32,6 +32,7 @@
import java.util.stream.Stream;

import io.helidon.common.GenericType;
import io.helidon.common.config.GlobalConfig;
import io.helidon.config.ConfigValue;
import io.helidon.config.MetaConfig;
import io.helidon.config.spi.ConfigMapper;
Expand Down Expand Up @@ -167,8 +168,8 @@ public static void buildTimeEnd() {
private ConfigDelegate doRegisterConfig(Config config, ClassLoader classLoader) {
ConfigDelegate currentConfig = CONFIGS.remove(classLoader);

if (config instanceof ConfigDelegate) {
config = ((ConfigDelegate) config).delegate();
if (config instanceof ConfigDelegate delegate) {
config = delegate.delegate();
}

if (null != currentConfig) {
Expand All @@ -178,6 +179,11 @@ private ConfigDelegate doRegisterConfig(Config config, ClassLoader classLoader)
ConfigDelegate newConfig = new ConfigDelegate(config);
CONFIGS.put(classLoader, newConfig);

if (classLoader == Thread.currentThread().getContextClassLoader()) {
// this should be the default class loader (we do not support classloader magic in Helidon)
GlobalConfig.config(() -> newConfig, true);
}

return newConfig;
}

Expand Down
11 changes: 7 additions & 4 deletions config/config/src/main/java/io/helidon/config/BuilderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class BuilderImpl implements Config.Builder {
private MergingStrategy mergingStrategy = MergingStrategy.fallback();
private boolean hasSystemPropertiesSource;
private boolean hasEnvVarSource;
private boolean sourcesConfigured;
/*
* Config mapper providers
*/
Expand Down Expand Up @@ -123,6 +124,8 @@ public Config.Builder sources(List<Supplier<? extends ConfigSource>> sourceSuppl
sourceSuppliers.stream()
.map(Supplier::get)
.forEach(this::addSource);
// this was intentional, even if empty (such as from Config.just())
this.sourcesConfigured = true;

return this;
}
Expand Down Expand Up @@ -427,14 +430,14 @@ private ConfigSourcesRuntime buildConfigSources(ConfigContextImpl context) {
envVarAliasGeneratorEnabled = true;
}

boolean nothingConfigured = sources.isEmpty();
boolean nothingConfigured = sources.isEmpty() && !sourcesConfigured;

if (nothingConfigured) {
// use meta configuration to load all sources
MetaConfig.configSources(mediaType -> context.findParser(mediaType).isPresent(), context.supportedSuffixes())
.stream()
MetaConfigFinder.findConfigSource(mediaType -> context.findParser(mediaType).isPresent(),
context.supportedSuffixes())
.map(context::sourceRuntimeBase)
.forEach(targetSources::add);
.ifPresent(targetSources::add);
} else {
// add all configured or discovered sources

Expand Down
10 changes: 8 additions & 2 deletions config/config/src/main/java/io/helidon/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -1635,8 +1635,14 @@ default Builder sources(Supplier<? extends ConfigSource> configSource,
* @see #config(Config)
*/
default Builder metaConfig() {
MetaConfig.metaConfig()
.ifPresent(this::config);
try {
MetaConfig.metaConfig()
.ifPresent(this::config);
} catch (Exception e) {
System.getLogger(getClass().getName())
.log(System.Logger.Level.WARNING, "Failed to load SE meta-configuration,"
+ " please make sure it has correct format.", e);
}

return this;
}
Expand Down
13 changes: 0 additions & 13 deletions config/config/src/main/java/io/helidon/config/MetaConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Function;

import io.helidon.common.HelidonServiceLoader;
import io.helidon.common.media.type.MediaType;
Expand Down Expand Up @@ -241,18 +240,6 @@ static List<ConfigSource> configSources(Config metaConfig) {
return configSources;
}

// only interested in config source
static List<ConfigSource> configSources(Function<MediaType, Boolean> supportedMediaType, List<String> supportedSuffixes) {
Optional<Config> metaConfigOpt = metaConfig();

return metaConfigOpt
.map(MetaConfig::configSources)
.orElseGet(() -> MetaConfigFinder.findConfigSource(supportedMediaType, supportedSuffixes)
.map(List::of)
.orElseGet(List::of));

}

private static Config createDefault() {
// use defaults
Config.Builder builder = Config.builder();
Expand Down
3 changes: 3 additions & 0 deletions config/tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,8 @@
<module>config-metadata-meta-api</module>
<module>config-metadata-builder-api</module>
<module>test-lazy-source</module>
<module>test-no-config-sources</module>
<module>test-default-config-source</module>
<module>test-mp-se-meta</module>
</modules>
</project>
63 changes: 63 additions & 0 deletions config/tests/test-default-config-source/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.helidon.config.tests</groupId>
<artifactId>helidon-config-tests-project</artifactId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>helidon-test-default-config-source</artifactId>
<name>Helidon Config Tests Default Config Source</name>

<description>
Test that when no config sources are configured, we do not fall to meta config, but we want to
use default config sources
</description>

<dependencies>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.common.testing</groupId>
<artifactId>helidon-common-testing-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# Copyright (c) 2024 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.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

value: "from-file"
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# Copyright (c) 2024 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.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# MP style, which would normally fail in Helidon SE, but should be ignored, as we do not specify meta config
add-default-sources: true
sources:
- type: "properties"
classpath: "app.properties"
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.config.tests.nosources;

import java.util.Optional;

import io.helidon.config.Config;

import org.junit.jupiter.api.Test;

import static io.helidon.common.testing.junit5.OptionalMatcher.optionalValue;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class DefaultSourceTest {
@Test
public void testDefaultSource() {
Config config = Config.builder()
.disableSystemPropertiesSource()
.disableEnvironmentVariablesSource()
.build();

Optional<String> value = config.get("value")
.asString()
.asOptional();

// meta config MUST be ignored
assertThat("We defined not sources, we should fall back to default application.yaml",
value,
optionalValue(is("from-file")));
}
}
67 changes: 67 additions & 0 deletions config/tests/test-mp-se-meta/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.helidon.config.tests</groupId>
<artifactId>helidon-config-tests-project</artifactId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>helidon-config-tests-mp-se-meta</artifactId>
<name>Helidon Config Tests MP SE Meta</name>

<description>
Test that when using MP config with meta-config file name that conflicts with Helidon SE, everything
works as expected.
</description>

<dependencies>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-mp</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.common.testing</groupId>
<artifactId>helidon-common-testing-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
17 changes: 17 additions & 0 deletions config/tests/test-mp-se-meta/src/main/resources/app.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# Copyright (c) 2024 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.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

helidon.test.value=value
Loading

0 comments on commit 2397b81

Please sign in to comment.