ext = Optional.of(base.orElse(what))
+ .filter(f -> f.contains("."))
+ .map(f -> f.substring(f.lastIndexOf(".") + 1));
+ return ext.isPresent() ? what : what + HOCON_EXTENSION;
+ }
+}
diff --git a/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/HoconMpConfigSource.java b/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/HoconMpConfigSource.java
new file mode 100644
index 00000000000..5de2eb647a5
--- /dev/null
+++ b/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/HoconMpConfigSource.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 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.
+ * 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.hocon.mp;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import io.helidon.config.ConfigException;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigList;
+import com.typesafe.config.ConfigObject;
+import com.typesafe.config.ConfigParseOptions;
+import com.typesafe.config.ConfigResolveOptions;
+import com.typesafe.config.ConfigValue;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+
+/**
+ * MicroProfile {@link org.eclipse.microprofile.config.spi.ConfigSource} that can be used
+ * to add HOCON/JSON files from classpath or file system using the
+ * {@link org.eclipse.microprofile.config.spi.ConfigProviderResolver#getBuilder()}.
+ * The HOCON/JSON file is transformed to a flat map as follows:
+ * Object nodes
+ *
+ * Each node in the tree is dot separated.
+ *
+ * server = {
+ * host = "localhost"
+ * port= 8080
+ * }
+ *
+ * Will be transformed to the following properties:
+ *
+ * server.host=localhost
+ * server.port=8080
+ *
+ * List nodes (arrays)
+ *
+ * Each node will be indexed (0 based)
+ *
+ * providers =
+ * [{abac = {enabled = true}}]
+ * names = [
+ * first
+ * second
+ * third
+ * ]
+ *
+ * Will be transformed to the following properties:
+ *
+ * providers.0.abac.enabled=true
+ * names.0=first
+ * names.1=second
+ * names.2=third
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class HoconMpConfigSource implements ConfigSource {
+ private final String name;
+ private Map properties;
+
+ private static final boolean RESOLVING_ENABLED = true;
+ private static final ConfigResolveOptions RESOLVE_OPTIONS = ConfigResolveOptions.defaults();
+
+ private HoconMpConfigSource(String name, Map properties) {
+ this.properties = properties;
+ this.name = "hocon: " + name;
+ }
+
+ /**
+ * Load a HOCON/JSON config source from file system.
+ *
+ * @param path path to the HOCON/JSON file
+ * @return config source loaded from the file
+ * @see #create(java.net.URL)
+ */
+ public static ConfigSource create(Path path) {
+ String name = path.toAbsolutePath().toString();
+
+ try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
+ ConfigParseOptions parseOptions = getConfigParseOptions(path);
+
+ Config typesafeConfig = toConfig(reader, parseOptions);
+ // this is a mutable HashMap that we can use
+ Map props =
+ fromConfig(typesafeConfig.root().isEmpty() ? ConfigFactory.empty().root() : typesafeConfig.root());
+ return new HoconMpConfigSource(name, props);
+ } catch (IOException e) {
+ throw new ConfigException("Failed to load HOCON/JSON config source from path: " + path.toAbsolutePath(), e);
+ }
+ }
+
+ /**
+ * Load a HOCON/JSON config source from URL.
+ * The URL may be any URL which is supported by the used JVM.
+ *
+ * @param url url of the resource
+ * @return config source loaded from the URL
+ */
+ public static ConfigSource create(URL url) {
+ try (InputStreamReader reader = new InputStreamReader(url.openConnection().getInputStream(), StandardCharsets.UTF_8)) {
+ String name = url.toString();
+ ConfigParseOptions parseOptions = getConfigParseOptions(url);
+ Config typesafeConfig = toConfig(reader, parseOptions);
+ if (typesafeConfig.root().isEmpty()) { // empty source
+ return new HoconMpConfigSource(name, Map.of());
+ }
+ return new HoconMpConfigSource(name, fromConfig(typesafeConfig.root()));
+ } catch (Exception e) {
+ throw new ConfigException("Failed to configure HOCON/JSON config source", e);
+ }
+ }
+
+ private static ConfigParseOptions getConfigParseOptions(URL url) {
+ HoconMpConfigIncluder includer = new HoconMpConfigIncluder();
+ ConfigParseOptions parseOptions = ConfigParseOptions.defaults().appendIncluder(includer);
+ includer.parseOptions(parseOptions);
+ includer.relativeUrl(getParentResourcePath(url.toString()));
+ includer.charset(StandardCharsets.UTF_8);
+ return parseOptions;
+ }
+
+ private static ConfigParseOptions getConfigParseOptions(Path path) {
+ HoconMpConfigIncluder includer = new HoconMpConfigIncluder();
+ ConfigParseOptions parseOptions = ConfigParseOptions.defaults().appendIncluder(includer);
+ includer.parseOptions(parseOptions);
+ includer.relativePath(path.getParent());
+ includer.charset(StandardCharsets.UTF_8);
+ return parseOptions;
+ }
+
+ private static Config toConfig(Reader content, ConfigParseOptions parseOptions) {
+ Config typesafeConfig = ConfigFactory.parseReader(
+ content, parseOptions);
+ if (RESOLVING_ENABLED) {
+ typesafeConfig = typesafeConfig.resolve(RESOLVE_OPTIONS);
+ }
+ return typesafeConfig;
+ }
+
+ /**
+ * Create from HOCON/JSON file(s) on classpath.
+ *
+ * @param resource resource name to locate on classpath (looks for all instances)
+ * @return list of config sources discovered (may be zero length)
+ */
+ public static List classPath(String resource) {
+ List sources = new LinkedList<>();
+ try {
+ Thread.currentThread().getContextClassLoader().getResources(resource)
+ .asIterator()
+ .forEachRemaining(it -> sources.add(create(it)));
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read HOCON/JSON \"" + resource + "\" from classpath", e);
+ }
+
+ return sources;
+ }
+
+ /**
+ * Create from HOCON/JSON file(s) on classpath with profile support.
+ *
+ * @param resource resource name to locate on classpath (looks for all instances)
+ * @param profile name of the profile to use
+ * @return list of config sources discovered (may be zero length)
+ */
+ public static List classPath(String resource, String profile) {
+ Objects.requireNonNull(profile, "Profile must be defined");
+
+ List sources = new LinkedList<>();
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ try {
+ Enumeration baseResources = classLoader.getResources(resource);
+ Enumeration profileResources = classLoader.getResources(toProfileResource(resource, profile));
+
+ if (profileResources.hasMoreElements()) {
+ List profileResourceList = new LinkedList<>();
+ profileResources.asIterator()
+ .forEachRemaining(profileResourceList::add);
+
+ baseResources.asIterator()
+ .forEachRemaining(it -> {
+ String pathBase = pathBase(it.toString());
+ // we need to find profile that belongs to this
+ for (URL url : profileResourceList) {
+ String profilePathBase = pathBase(url.toString());
+ if (pathBase.equals(profilePathBase)) {
+ // Main is the profile config file and fallback is the original config file
+ sources.add(create(create(url), create(it)));
+ } else {
+ sources.add(create(it));
+ }
+ }
+ });
+ } else {
+ baseResources
+ .asIterator()
+ .forEachRemaining(it -> sources.add(create(it)));
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read HOCON/JSON \"" + resource + "\" from classpath", e);
+ }
+
+ return sources;
+ }
+
+ private static ConfigSource create(ConfigSource main, ConfigSource fallback) {
+ String name = main.getName() + " (" + fallback.getName() + ")";
+
+ return new ConfigSource() {
+ @Override
+ public Set getPropertyNames() {
+ Set result = new HashSet<>(fallback.getPropertyNames());
+ result.addAll(main.getPropertyNames());
+
+ return result;
+ }
+
+ @Override
+ public String getValue(String propertyName) {
+ String value = main.getValue(propertyName);
+ if (value == null) {
+ return fallback.getValue(propertyName);
+ }
+ return value;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Map getProperties() {
+ Map result = new HashMap<>(fallback.getProperties());
+ result.putAll(main.getProperties());
+
+ return result;
+ }
+ };
+ }
+
+ private static String getParentResourcePath(String resource) {
+ // this works the same on windows and Unix systems (classpath is always forward slashes)
+ int lastSlash = resource.lastIndexOf('/');
+ String rootOfResource;
+ if (lastSlash > -1) {
+ rootOfResource = resource.substring(0, lastSlash + 1);
+ } else {
+ rootOfResource = resource;
+ }
+ return rootOfResource;
+ }
+
+ private static Map fromConfig(ConfigObject config) {
+ Map result = new HashMap<>();
+ process(result, "", config);
+
+ return result;
+ }
+
+ private static void process(Map resultMap, String prefix, ConfigObject config) {
+ config.forEach((unescapedKey, value) -> {
+ String key = io.helidon.config.Config.Key.escapeName(unescapedKey);
+ processNext(resultMap, prefix(prefix, key), value);
+ });
+ }
+
+ private static void process(Map resultMap, String prefix, ConfigList configList) {
+ int counter = 0;
+ for (ConfigValue value : configList) {
+ processNext(resultMap, prefix(prefix, String.valueOf(counter)), value);
+ counter++;
+ }
+ }
+
+ private static void processNext(Map resultMap,
+ String prefix,
+ ConfigValue value) {
+ if (value instanceof ConfigList) {
+ process(resultMap, prefix, (ConfigList) value);
+ } else if (value instanceof ConfigObject) {
+ process(resultMap, prefix, (ConfigObject) value);
+ } else {
+ Object unwrapped = value.unwrapped();
+ String stringValue = (null == unwrapped) ? "" : String.valueOf(unwrapped);
+ resultMap.put(prefix, stringValue);
+ }
+ }
+
+ private static String prefix(String prefix, String stringKey) {
+ if (prefix.isEmpty()) {
+ return stringKey;
+ }
+
+ return prefix + "." + stringKey;
+ }
+
+ private static String pathBase(String path) {
+ int i = path.lastIndexOf('/');
+ int y = path.lastIndexOf('!');
+ int z = path.lastIndexOf(':');
+ int b = path.lastIndexOf('\\');
+
+ // we need the last index before the file name - so the highest number of all of the above
+ int max = Math.max(i, y);
+ max = Math.max(max, z);
+ max = Math.max(max, b);
+
+ if (max > -1) {
+ return path.substring(0, max);
+ }
+ return path;
+ }
+
+ private static String toProfileResource(String resource, String profile) {
+ int i = resource.lastIndexOf('.');
+ if (i > -1) {
+ return resource.substring(0, i) + "-" + profile + resource.substring(i);
+ }
+ return resource + "-" + profile;
+ }
+
+ @Override
+ public Set getPropertyNames() {
+ return Collections.unmodifiableSet(properties.keySet());
+ }
+
+ @Override
+ public Map getProperties() {
+ return Collections.unmodifiableMap(properties);
+ }
+
+ @Override
+ public String getValue(String propertyName) {
+ return properties.get(propertyName);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
diff --git a/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/HoconMpMetaConfigProvider.java b/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/HoconMpMetaConfigProvider.java
new file mode 100644
index 00000000000..258ee448191
--- /dev/null
+++ b/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/HoconMpMetaConfigProvider.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 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.
+ * 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.hocon.mp;
+
+import java.util.List;
+import java.util.Set;
+
+import io.helidon.common.Prioritized;
+import io.helidon.config.Config;
+import io.helidon.config.mp.MpMetaConfigUtils;
+import io.helidon.config.mp.spi.MpMetaConfigProvider;
+
+import org.eclipse.microprofile.config.spi.ConfigSource;
+
+/**
+ * Helidon MicroProfile meta-config provider for Hocon and Json.
+ */
+public class HoconMpMetaConfigProvider implements MpMetaConfigProvider, Prioritized {
+ @Override
+ public Set supportedTypes() {
+ return Set.of("hocon", "json");
+ }
+
+ @Override
+ public List extends ConfigSource> create(String type, Config metaConfig, String profile) {
+ return MpMetaConfigUtils.sourceFromMeta(
+ metaConfig,
+ profile,
+ HoconMpConfigSource::create,
+ HoconMpConfigSource::classPath,
+ HoconMpConfigSource::classPath,
+ HoconMpConfigSource::create
+ );
+ }
+
+ @Override
+ public int priority() {
+ return 300;
+ }
+}
diff --git a/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/package-info.java b/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/package-info.java
new file mode 100644
index 00000000000..cc1a7e502d7
--- /dev/null
+++ b/config/hocon-mp/src/main/java/io/helidon/config/hocon/mp/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 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.
+ * 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.
+ */
+
+/**
+ * HOCON config source for MicroProfile config.
+ *
+ * @see io.helidon.config Configuration API
+ */
+package io.helidon.config.hocon.mp;
diff --git a/config/hocon-mp/src/main/java/module-info.java b/config/hocon-mp/src/main/java/module-info.java
new file mode 100644
index 00000000000..df4f2dcea0c
--- /dev/null
+++ b/config/hocon-mp/src/main/java/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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.
+ * 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.
+ */
+
+/**
+ * Support for HOCON configuration sources.
+ */
+module io.helidon.config.hocon.mp {
+ requires microprofile.config.api;
+
+ requires io.helidon.config.mp;
+ requires transitive io.helidon.config;
+ // requires io.helidon.config.hocon;
+ requires typesafe.config;
+
+ exports io.helidon.config.hocon.mp;
+
+ provides io.helidon.config.mp.spi.MpMetaConfigProvider with io.helidon.config.hocon.mp.HoconMpMetaConfigProvider;
+
+}
diff --git a/config/hocon-mp/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-hocon-mp/native-image.properties b/config/hocon-mp/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-hocon-mp/native-image.properties
new file mode 100644
index 00000000000..5347fb8a838
--- /dev/null
+++ b/config/hocon-mp/src/main/resources/META-INF/native-image/io.helidon.config/helidon-config-hocon-mp/native-image.properties
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+Args=--initialize-at-build-time=io.helidon.config.hocon.mp
diff --git a/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpConfigSourceTest.java b/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpConfigSourceTest.java
new file mode 100644
index 00000000000..517dca09244
--- /dev/null
+++ b/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpConfigSourceTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 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.
+ * 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.hocon.mp;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+
+import org.eclipse.microprofile.config.spi.ConfigSource;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class HoconJsonMpConfigSourceTest {
+ @Test
+ void testHoconViaClasspath() throws IOException {
+ ConfigSource source = HoconMpConfigSource.create(getResourceUrlPath("application.conf"));
+ // Test Main Config
+ validateHoconConfig(source);
+ }
+
+ @Test
+ void testHoconViaPath() {
+ ConfigSource source = HoconMpConfigSource.create(Paths.get("src/test/resources/application.conf")) ;
+ validateHoconConfig(source);
+ }
+
+ private void validateHoconConfig(ConfigSource source) {
+ // Test Main Config
+ assertThat(source.getValue("hocon.string"), is("String"));
+ assertThat(source.getValue("hocon.number"), is("10"));
+ assertThat(source.getValue("hocon.array.0"), is("Array 1"));
+ assertThat(source.getValue("hocon.array.1"), is("Array 2"));
+ assertThat(source.getValue("hocon.array.2"), is("Array 3"));
+ assertThat(source.getValue("hocon.boolean"), is("true"));
+ // Test Include
+ assertThat(source.getValue("hocon_include.string"), is("Include String"));
+ assertThat(source.getValue("hocon_include.number"), is("20"));
+ assertThat(source.getValue("hocon_include.array.0"), is("Include Array 1"));
+ assertThat(source.getValue("hocon_include.array.1"), is("Include Array 2"));
+ assertThat(source.getValue("hocon_include.array.2"), is("Include Array 3"));
+ assertThat(source.getValue("hocon_include.boolean"), is("false"));
+ }
+
+ @Test
+ void testJsonConfigViaClassPath() throws IOException {
+ ConfigSource source = HoconMpConfigSource.create(getResourceUrlPath("application.json"));
+ validateJsonConfig(source);
+ }
+
+ @Test
+ void testJsonConfigViaPath() throws IOException {
+ ConfigSource source = HoconMpConfigSource.create(Paths.get("src/test/resources/application.json"));
+ validateJsonConfig(source);
+ }
+
+ private void validateJsonConfig(ConfigSource source) {
+ assertThat(source.getValue("json.string"), is("String"));
+ assertThat(source.getValue("json.number"), is("10"));
+ assertThat(source.getValue("json.array.0"), is("Array 1"));
+ assertThat(source.getValue("json.array.1"), is("Array 2"));
+ assertThat(source.getValue("json.array.2"), is("Array 3"));
+ assertThat(source.getValue("json.boolean"), is("true"));
+ }
+
+ private static URL getResourceUrlPath(String resource) throws IOException {
+ Enumeration resources = Thread.currentThread().getContextClassLoader().getResources(resource);
+ while (resources.hasMoreElements()) {
+ return resources.nextElement();
+ }
+ return null;
+ }
+}
diff --git a/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpMetaConfigTest.java b/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpMetaConfigTest.java
new file mode 100644
index 00000000000..b550e679551
--- /dev/null
+++ b/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpMetaConfigTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 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.
+ * 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.hocon.mp;
+
+import io.helidon.config.ConfigException;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class HoconJsonMpMetaConfigTest {
+ private static ConfigProviderResolver configResolver;
+ private Config config;
+ private static final String META_CONFIG_SYSTEM_PROPERTY = "io.helidon.config.mp.meta-config";
+
+ @BeforeAll
+ static void getProviderResolver() {
+ configResolver = ConfigProviderResolver.instance();
+ }
+ @AfterAll
+ static void resetSystemProperties() {
+ System.clearProperty(META_CONFIG_SYSTEM_PROPERTY);
+ }
+
+ @BeforeEach
+ void resetConfig() {
+ if (config == null) {
+ // first run - need to remove existing props
+ System.clearProperty(META_CONFIG_SYSTEM_PROPERTY);
+ configResolver.releaseConfig(ConfigProvider.getConfig());
+ } else {
+ configResolver.releaseConfig(config);
+ config = null;
+ }
+ }
+
+ @Test
+ void testMetaHoconClasspath() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-hocon-classpath.yaml");
+ validateConfig();
+ }
+
+ @Test
+ void testMetaHoconPath() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-hocon-path.yaml");
+ validateConfig();
+ }
+
+ private void validateConfig() {
+ config = ConfigProvider.getConfig();
+
+ // Main file
+ assertThat(config.getValue("string", String.class), is("String"));
+ assertThat(config.getValue("number", String.class), is("175"));
+ assertThat(config.getValue("array.0", String.class), is("One"));
+ assertThat(config.getValue("array.1", String.class), is("Two"));
+ assertThat(config.getValue("array.2", String.class), is("Three"));
+ assertThat(config.getValue("boolean", String.class), is("true"));
+ // Include file
+ assertThat(config.getValue("custom_include.string", String.class), is("Include_String"));
+ assertThat(config.getValue("custom_include.number", String.class), is("200"));
+ assertThat(config.getValue("custom_include.array.0", String.class), is("First"));
+ assertThat(config.getValue("custom_include.array.1", String.class), is("Second"));
+ assertThat(config.getValue("custom_include.array.2", String.class), is("Third"));
+ assertThat(config.getValue("custom_include.boolean", String.class), is("false"));
+ }
+
+ @Test
+ void testMetaHoconClasspathConfigProfile() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-hocon-classpath-profile.yaml");
+ validateConfigProfile();
+ }
+
+ @Test
+ void testMetaHoconPathConfigProfile() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-hocon-path-profile.yaml");
+ validateConfigProfile();
+ }
+
+ private void validateConfigProfile() {
+ config = ConfigProvider.getConfig();
+
+ // Main file
+ assertThat(config.getValue("string", String.class), is("String_dev"));
+ assertThat(config.getValue("number", String.class), is("250"));
+ assertThat(config.getValue("array.0", String.class), is("One"));
+ assertThat(config.getValue("array.1", String.class), is("Two"));
+ assertThat(config.getValue("array.2", String.class), is("Three"));
+ assertThat(config.getValue("boolean", String.class), is("true"));
+ assertThat(config.getValue("extra", String.class), is("Extra"));
+
+ // Include file
+ assertThat(config.getValue("custom_include.string", String.class), is("Include_String"));
+ assertThat(config.getValue("custom_include.number", String.class), is("200"));
+ assertThat(config.getValue("custom_include.array.0", String.class), is("Begin"));
+ assertThat(config.getValue("custom_include.array.1", String.class), is("Middle"));
+ assertThat(config.getValue("custom_include.array.2", String.class), is("End"));
+ assertThat(config.getValue("custom_include.boolean", String.class), is("true"));
+ }
+
+
+ @Test
+ void testMetaJson() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-json.yaml");
+ config = ConfigProvider.getConfig();
+
+ assertThat(config.getValue("string", String.class), is("String"));
+ assertThat(config.getValue("number", String.class), is("175"));
+ assertThat(config.getValue("array.0", String.class), is("One"));
+ assertThat(config.getValue("array.1", String.class), is("Two"));
+ assertThat(config.getValue("array.2", String.class), is("Three"));
+ assertThat(config.getValue("boolean", String.class), is("true"));
+ }
+
+ @Test
+ void testMetaOrdinal() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "ordinal-mp-meta-config-hocon.yaml");
+ config = ConfigProvider.getConfig();
+
+ assertThat(config.getValue("string", String.class), is("String"));
+ assertThat(config.getValue("number", String.class), is("175"));
+ assertThat(config.getValue("array.0", String.class), is("First"));
+ assertThat(config.getValue("array.1", String.class), is("Second"));
+ assertThat(config.getValue("array.2", String.class), is("Third"));
+ assertThat(config.getValue("boolean", String.class), is("false"));
+ }
+
+ @Test
+ void testMetaHoconNonExistentNotOptional() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-hocon-path-not-optional.yaml");
+ try {
+ config = ConfigProvider.getConfig();
+ Assertions.fail("Expecting meta-config to fail due to not optional non-existent config source");
+ } catch (ConfigException e) {}
+ }
+}
diff --git a/config/hocon-mp/src/test/resources/application.conf b/config/hocon-mp/src/test/resources/application.conf
new file mode 100644
index 00000000000..1ca37739357
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/application.conf
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+include "include.conf"
+
+hocon = {
+ string = "String"
+ number = 10
+ array = [
+ "Array 1"
+ "Array 2"
+ "Array 3"
+ ]
+ boolean = true
+}
diff --git a/config/hocon-mp/src/test/resources/application.json b/config/hocon-mp/src/test/resources/application.json
new file mode 100644
index 00000000000..5979a65e88b
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/application.json
@@ -0,0 +1,12 @@
+{
+ "json": {
+ "string": "String",
+ "number": 10,
+ "array": [
+ "Array 1",
+ "Array 2",
+ "Array 3"
+ ],
+ "boolean": true
+ }
+}
diff --git a/config/hocon-mp/src/test/resources/custom-application-dev.conf b/config/hocon-mp/src/test/resources/custom-application-dev.conf
new file mode 100644
index 00000000000..5b06273d36d
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-application-dev.conf
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+include "custom-include-dev.conf"
+
+string = String_dev
+number = 250
+extra = Extra
+
diff --git a/config/hocon-mp/src/test/resources/custom-application.conf b/config/hocon-mp/src/test/resources/custom-application.conf
new file mode 100644
index 00000000000..09eca799183
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-application.conf
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+include "custom-include.conf"
+
+string = String
+number = 175
+array = [
+ One
+ Two
+ Three
+]
+boolean = true
diff --git a/config/hocon-mp/src/test/resources/custom-application.json b/config/hocon-mp/src/test/resources/custom-application.json
new file mode 100644
index 00000000000..08cb127271e
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-application.json
@@ -0,0 +1,10 @@
+{
+ "string": "String",
+ "number": 175,
+ "array": [
+ "One",
+ "Two",
+ "Three"
+ ],
+ "boolean": true
+}
diff --git a/config/hocon-mp/src/test/resources/custom-include-dev.conf b/config/hocon-mp/src/test/resources/custom-include-dev.conf
new file mode 100644
index 00000000000..98a220a45e1
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-include-dev.conf
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+custom_include {
+ array = [
+ Begin
+ Middle
+ End
+ ]
+ boolean = true
+}
diff --git a/config/hocon-mp/src/test/resources/custom-include.conf b/config/hocon-mp/src/test/resources/custom-include.conf
new file mode 100644
index 00000000000..c75b064276e
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-include.conf
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+custom_include {
+ string = Include_String
+ number = 200
+ array = [
+ First
+ Second
+ Third
+ ]
+ boolean = false
+}
diff --git a/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-classpath-profile.yaml b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-classpath-profile.yaml
new file mode 100644
index 00000000000..7d114fa309c
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-classpath-profile.yaml
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+profile: dev
+
+sources:
+ - type: "hocon"
+ classpath: "custom-application.conf"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-classpath.yaml b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-classpath.yaml
new file mode 100644
index 00000000000..362529a681b
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-classpath.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "hocon"
+ classpath: "custom-application.conf"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path-not-optional.yaml b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path-not-optional.yaml
new file mode 100644
index 00000000000..2d5994fb98a
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path-not-optional.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "hocon"
+ path: "src/test/resources/non-existent.conf"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path-profile.yaml b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path-profile.yaml
new file mode 100644
index 00000000000..2ee86556fe4
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path-profile.yaml
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+profile: dev
+
+sources:
+ - type: "hocon"
+ path: "src/test/resources/custom-application.conf"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path.yaml b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path.yaml
new file mode 100644
index 00000000000..41a09ac3c89
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-mp-meta-config-hocon-path.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "hocon"
+ path: "src/test/resources/custom-application.conf"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/custom-mp-meta-config-json.yaml b/config/hocon-mp/src/test/resources/custom-mp-meta-config-json.yaml
new file mode 100644
index 00000000000..c34c2315f1b
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/custom-mp-meta-config-json.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "json"
+ classpath: "custom-application.json"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/include.conf b/config/hocon-mp/src/test/resources/include.conf
new file mode 100644
index 00000000000..32d5814b1ee
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/include.conf
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+hocon_include {
+ string = "Include String"
+ number = 20
+ array = [
+ "Include Array 1"
+ "Include Array 2"
+ "Include Array 3"
+ ]
+ boolean = false
+}
diff --git a/config/hocon-mp/src/test/resources/ordinal-mp-meta-config-hocon.yaml b/config/hocon-mp/src/test/resources/ordinal-mp-meta-config-hocon.yaml
new file mode 100644
index 00000000000..250cd984d82
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/ordinal-mp-meta-config-hocon.yaml
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "json"
+ classpath: "ordinal.json"
+ optional: false
+ ordinal: 500
+ - type: "hocon"
+ classpath: "ordinal.conf"
+ optional: false
diff --git a/config/hocon-mp/src/test/resources/ordinal.conf b/config/hocon-mp/src/test/resources/ordinal.conf
new file mode 100644
index 00000000000..09eca799183
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/ordinal.conf
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+include "custom-include.conf"
+
+string = String
+number = 175
+array = [
+ One
+ Two
+ Three
+]
+boolean = true
diff --git a/config/hocon-mp/src/test/resources/ordinal.json b/config/hocon-mp/src/test/resources/ordinal.json
new file mode 100644
index 00000000000..f8dcee08fd3
--- /dev/null
+++ b/config/hocon-mp/src/test/resources/ordinal.json
@@ -0,0 +1,8 @@
+{
+ "array": [
+ "First",
+ "Second",
+ "Third"
+ ],
+ "boolean": false
+}
diff --git a/config/pom.xml b/config/pom.xml
index 08b7810202d..41a5baa3e26 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -50,6 +50,7 @@
yaml-mp
metadata
metadata-processor
+ hocon-mp
diff --git a/config/yaml-mp/pom.xml b/config/yaml-mp/pom.xml
index b9e5d1cfb1a..282307e994b 100644
--- a/config/yaml-mp/pom.xml
+++ b/config/yaml-mp/pom.xml
@@ -38,6 +38,10 @@
+
+ io.helidon.config
+ helidon-config-mp
+
io.helidon.config
helidon-config-yaml
diff --git a/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMetaConfigProvider.java b/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMetaConfigProvider.java
new file mode 100644
index 00000000000..88d876464e2
--- /dev/null
+++ b/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMetaConfigProvider.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 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.
+ * 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.yaml.mp;
+
+import java.util.List;
+import java.util.Set;
+
+import io.helidon.common.Prioritized;
+import io.helidon.config.Config;
+import io.helidon.config.mp.MpMetaConfigUtils;
+import io.helidon.config.mp.spi.MpMetaConfigProvider;
+
+import org.eclipse.microprofile.config.spi.ConfigSource;
+
+/**
+ * Helidon MicroProfile meta-config provider for Yaml.
+ */
+public class YamlMetaConfigProvider implements MpMetaConfigProvider, Prioritized {
+ @Override
+ public Set supportedTypes() {
+ return Set.of("yaml");
+ }
+
+ @Override
+ public List extends ConfigSource> create(String type, Config metaConfig, String profile) {
+ return MpMetaConfigUtils.sourceFromMeta(
+ metaConfig,
+ profile,
+ YamlMpConfigSource::create,
+ YamlMpConfigSource::classPath,
+ YamlMpConfigSource::classPath,
+ YamlMpConfigSource::create
+ );
+ }
+
+ @Override
+ public int priority() {
+ return 300;
+ }
+}
diff --git a/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMpConfigSource.java b/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMpConfigSource.java
index ac01428c46f..3e1d60c8f29 100644
--- a/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMpConfigSource.java
+++ b/config/yaml-mp/src/main/java/io/helidon/config/yaml/mp/YamlMpConfigSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 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.
@@ -217,7 +217,8 @@ public static List classPath(String resource, String profile) {
for (URL url : profileResourceList) {
String profilePathBase = pathBase(url.toString());
if (pathBase.equals(profilePathBase)) {
- sources.add(create(create(it), create(url)));
+ // Main is the profile config file and fallback is the original config file
+ sources.add(create(create(url), create(it)));
} else {
sources.add(create(it));
}
diff --git a/config/yaml-mp/src/main/java/module-info.java b/config/yaml-mp/src/main/java/module-info.java
index 7017a0af9ba..b397f5d9575 100644
--- a/config/yaml-mp/src/main/java/module-info.java
+++ b/config/yaml-mp/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 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.
@@ -21,10 +21,12 @@
requires org.yaml.snakeyaml;
requires microprofile.config.api;
+ requires io.helidon.config.mp;
requires transitive io.helidon.config;
requires io.helidon.config.yaml;
exports io.helidon.config.yaml.mp;
provides org.eclipse.microprofile.config.spi.ConfigSourceProvider with io.helidon.config.yaml.mp.YamlConfigSourceProvider;
-}
\ No newline at end of file
+ provides io.helidon.config.mp.spi.MpMetaConfigProvider with io.helidon.config.yaml.mp.YamlMetaConfigProvider;
+}
diff --git a/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpConfigSourceTest.java b/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpConfigSourceTest.java
index 7210b009597..99d2b7c40c4 100644
--- a/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpConfigSourceTest.java
+++ b/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpConfigSourceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 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.
@@ -16,7 +16,11 @@
package io.helidon.config.yaml.mp;
+import java.io.IOException;
import java.io.StringReader;
+import java.net.URL;
+import java.nio.file.Paths;
+import java.util.Enumeration;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.junit.jupiter.api.Test;
@@ -48,4 +52,33 @@ void testListNode() {
assertThat(source.getValue("names.1"), is("second"));
assertThat(source.getValue("names.2"), is("third"));
}
+
+ @Test
+ void testConfigViaClassPath() throws IOException {
+ ConfigSource source = YamlMpConfigSource.create(getResourceUrlPath("application.yaml"));
+ validateConfig(source);
+ }
+
+ @Test
+ void testConfigViaPath() throws IOException {
+ ConfigSource source = YamlMpConfigSource.create(Paths.get("src/test/resources/application.yaml"));
+ validateConfig(source);
+ }
+
+ private void validateConfig(ConfigSource source) {
+ assertThat(source.getValue("yaml.string"), is("String"));
+ assertThat(source.getValue("yaml.number"), is("10"));
+ assertThat(source.getValue("yaml.array.0"), is("Array 1"));
+ assertThat(source.getValue("yaml.array.1"), is("Array 2"));
+ assertThat(source.getValue("yaml.array.2"), is("Array 3"));
+ assertThat(source.getValue("yaml.boolean"), is("true"));
+ }
+
+ private static URL getResourceUrlPath(String resource) throws IOException {
+ Enumeration resources = Thread.currentThread().getContextClassLoader().getResources(resource);
+ while (resources.hasMoreElements()) {
+ return resources.nextElement();
+ }
+ return null;
+ }
}
diff --git a/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpMetaConfigTest.java b/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpMetaConfigTest.java
new file mode 100644
index 00000000000..97f887ab6da
--- /dev/null
+++ b/config/yaml-mp/src/test/java/io/helidon/config/yaml/mp/YamlMpMetaConfigTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 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.
+ * 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.yaml.mp;
+
+import io.helidon.config.ConfigException;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class YamlMpMetaConfigTest {
+ private static ConfigProviderResolver configResolver;
+ private Config config;
+ private static final String META_CONFIG_SYSTEM_PROPERTY = "io.helidon.config.mp.meta-config";
+
+ @BeforeAll
+ static void getProviderResolver() {
+ configResolver = ConfigProviderResolver.instance();
+ }
+ @AfterAll
+ static void resetSystemProperties() {
+ System.clearProperty(META_CONFIG_SYSTEM_PROPERTY);
+ }
+
+ @BeforeEach
+ void resetConfig() {
+ if (config == null) {
+ // first run - need to remove existing props
+ System.clearProperty(META_CONFIG_SYSTEM_PROPERTY);
+ configResolver.releaseConfig(ConfigProvider.getConfig());
+ } else {
+ configResolver.releaseConfig(config);
+ config = null;
+ }
+ }
+
+ @Test
+ void testMetaClasspath() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-classpath.yaml");
+ validateConfig();
+ }
+
+ @Test
+ void testMetaPath() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-path.yaml");
+ validateConfig();
+ }
+
+ private void validateConfig() {
+ config = ConfigProvider.getConfig();
+
+ // Main file
+ assertThat(config.getValue("string", String.class), is("String"));
+ assertThat(config.getValue("number", String.class), is("175"));
+ assertThat(config.getValue("array.0", String.class), is("One"));
+ assertThat(config.getValue("array.1", String.class), is("Two"));
+ assertThat(config.getValue("array.2", String.class), is("Three"));
+ assertThat(config.getValue("boolean", String.class), is("true"));
+ }
+
+ @Test
+ void testMetaClasspathConfigProfile() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-classpath-profile.yaml");
+ validateConfigProfile();
+ }
+
+ @Test
+ void testMetaPathConfigProfile() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-path-profile.yaml");
+ validateConfigProfile();
+ }
+
+ private void validateConfigProfile() {
+ config = ConfigProvider.getConfig();
+
+ // Main file
+ assertThat(config.getValue("string", String.class), is("String_dev"));
+ assertThat(config.getValue("number", String.class), is("250"));
+ assertThat(config.getValue("array.0", String.class), is("One"));
+ assertThat(config.getValue("array.1", String.class), is("Two"));
+ assertThat(config.getValue("array.2", String.class), is("Three"));
+ assertThat(config.getValue("boolean", String.class), is("true"));
+ assertThat(config.getValue("extra", String.class), is("Extra"));
+ }
+
+ @Test
+ void testMetaOrdinal() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "ordinal-mp-meta-config.yaml");
+ config = ConfigProvider.getConfig();
+
+ assertThat(config.getValue("string", String.class), is("String"));
+ assertThat(config.getValue("number", String.class), is("175"));
+ assertThat(config.getValue("array.0", String.class), is("First"));
+ assertThat(config.getValue("array.1", String.class), is("Second"));
+ assertThat(config.getValue("array.2", String.class), is("Third"));
+ assertThat(config.getValue("boolean", String.class), is("false"));
+ }
+
+ @Test
+ void testMetaNonExistentNotOptional() {
+ System.setProperty(META_CONFIG_SYSTEM_PROPERTY, "custom-mp-meta-config-path-not-optional.yaml");
+ try {
+ config = ConfigProvider.getConfig();
+ Assertions.fail("Expecting meta-config to fail due to not optional non-existent config source");
+ } catch (ConfigException e) {}
+ }
+}
diff --git a/config/yaml-mp/src/test/resources/application.yaml b/config/yaml-mp/src/test/resources/application.yaml
new file mode 100644
index 00000000000..dcf23a34e72
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/application.yaml
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+---
+yaml:
+ string: String
+ number: 10
+ array:
+ - "Array 1"
+ - "Array 2"
+ - "Array 3"
+ boolean: true
diff --git a/config/yaml-mp/src/test/resources/custom-application-dev.yaml b/config/yaml-mp/src/test/resources/custom-application-dev.yaml
new file mode 100644
index 00000000000..5dad87ff294
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/custom-application-dev.yaml
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+---
+string: String_dev
+number: 250
+extra: Extra
diff --git a/config/yaml-mp/src/test/resources/custom-application.yaml b/config/yaml-mp/src/test/resources/custom-application.yaml
new file mode 100644
index 00000000000..d4e37625be3
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/custom-application.yaml
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+---
+string: String
+number: 175
+array:
+ - One
+ - Two
+ - Three
+boolean: true
diff --git a/config/config-mp/src/test/resources/custom-mp-meta-config.yaml b/config/yaml-mp/src/test/resources/custom-mp-meta-config-classpath-profile.yaml
similarity index 60%
rename from config/config-mp/src/test/resources/custom-mp-meta-config.yaml
rename to config/yaml-mp/src/test/resources/custom-mp-meta-config-classpath-profile.yaml
index 745e2d161c4..4c6bc4d69f0 100644
--- a/config/config-mp/src/test/resources/custom-mp-meta-config.yaml
+++ b/config/yaml-mp/src/test/resources/custom-mp-meta-config-classpath-profile.yaml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021 Oracle and/or its affiliates.
+# Copyright (c) 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.
@@ -16,20 +16,9 @@
add-discovered-sources: false
add-discovered-converters: false
-#future compatibility
-#config-profile: "dev"
+profile: dev
sources:
- - type: "properties"
- path: "src/test/resources/meta-config/path.properties"
- ordinal: 50
- type: "yaml"
classpath: "custom-application.yaml"
- optional: true
- - type: "properties"
- classpath: "meta-config/classpath.properties"
- name: "CLASSPATH"
- # not sure how to test URL based unless we start a server
-# - type: "yaml"
-# url: "helidon-test:meta-config/url.yaml"
-# name: "URL"
\ No newline at end of file
+ optional: false
diff --git a/config/yaml-mp/src/test/resources/custom-mp-meta-config-classpath.yaml b/config/yaml-mp/src/test/resources/custom-mp-meta-config-classpath.yaml
new file mode 100644
index 00000000000..ce5d5680029
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/custom-mp-meta-config-classpath.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "yaml"
+ classpath: "custom-application.yaml"
+ optional: false
diff --git a/config/yaml-mp/src/test/resources/custom-mp-meta-config-path-not-optional.yaml b/config/yaml-mp/src/test/resources/custom-mp-meta-config-path-not-optional.yaml
new file mode 100644
index 00000000000..f029cc67198
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/custom-mp-meta-config-path-not-optional.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "yaml"
+ path: "src/test/resources/non-existent.conf"
+ optional: false
diff --git a/config/yaml-mp/src/test/resources/custom-mp-meta-config-path-profile.yaml b/config/yaml-mp/src/test/resources/custom-mp-meta-config-path-profile.yaml
new file mode 100644
index 00000000000..f2297b8cb57
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/custom-mp-meta-config-path-profile.yaml
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+profile: dev
+
+sources:
+ - type: "yaml"
+ path: "src/test/resources/custom-application.yaml"
+ optional: false
diff --git a/config/yaml-mp/src/test/resources/custom-mp-meta-config-path.yaml b/config/yaml-mp/src/test/resources/custom-mp-meta-config-path.yaml
new file mode 100644
index 00000000000..0f2c84bf7ee
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/custom-mp-meta-config-path.yaml
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "yaml"
+ path: "src/test/resources/custom-application.yaml"
+ optional: false
diff --git a/config/yaml-mp/src/test/resources/ordinal-2.yaml b/config/yaml-mp/src/test/resources/ordinal-2.yaml
new file mode 100644
index 00000000000..d4e37625be3
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/ordinal-2.yaml
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+---
+string: String
+number: 175
+array:
+ - One
+ - Two
+ - Three
+boolean: true
diff --git a/config/yaml-mp/src/test/resources/ordinal-mp-meta-config.yaml b/config/yaml-mp/src/test/resources/ordinal-mp-meta-config.yaml
new file mode 100644
index 00000000000..2b81e740e8b
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/ordinal-mp-meta-config.yaml
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+add-discovered-sources: false
+add-discovered-converters: false
+
+sources:
+ - type: "yaml"
+ classpath: "ordinal.yaml"
+ optional: false
+ ordinal: 500
+ - type: "yaml"
+ classpath: "ordinal-2.yaml"
+ optional: false
diff --git a/config/yaml-mp/src/test/resources/ordinal.yaml b/config/yaml-mp/src/test/resources/ordinal.yaml
new file mode 100644
index 00000000000..07074b86990
--- /dev/null
+++ b/config/yaml-mp/src/test/resources/ordinal.yaml
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+---
+array:
+- First
+- Second
+- Third
+boolean: false
diff --git a/examples/metrics/exemplar/pom.xml b/examples/metrics/exemplar/pom.xml
index 2cbdfd9892c..36e5e6543e5 100644
--- a/examples/metrics/exemplar/pom.xml
+++ b/examples/metrics/exemplar/pom.xml
@@ -40,6 +40,10 @@
io.helidon.webserver
helidon-webserver
+
+ io.helidon.config
+ helidon-config-yaml
+
io.helidon.media
helidon-media-jsonp
diff --git a/examples/metrics/filtering/se/pom.xml b/examples/metrics/filtering/se/pom.xml
index 7cd23c35f98..945eb09797f 100644
--- a/examples/metrics/filtering/se/pom.xml
+++ b/examples/metrics/filtering/se/pom.xml
@@ -38,6 +38,10 @@
io.helidon.webserver
helidon-webserver
+
+ io.helidon.config
+ helidon-config-yaml
+
io.helidon.media
helidon-media-jsonp
diff --git a/examples/metrics/kpi/pom.xml b/examples/metrics/kpi/pom.xml
index 1d391f2fbd5..98e6fa77355 100644
--- a/examples/metrics/kpi/pom.xml
+++ b/examples/metrics/kpi/pom.xml
@@ -38,6 +38,10 @@
io.helidon.webserver
helidon-webserver
+
+ io.helidon.config
+ helidon-config-yaml
+
io.helidon.media
helidon-media-jsonp
diff --git a/microprofile/cdi/pom.xml b/microprofile/cdi/pom.xml
index f8fa2105a72..10480639a71 100644
--- a/microprofile/cdi/pom.xml
+++ b/microprofile/cdi/pom.xml
@@ -1,6 +1,6 @@
+
+
+ 4.0.0
+
+ io.helidon.tests.integration
+ helidon-tests-integration-config
+ 2.5.1-SNAPSHOT
+
+
+ helidon-tests-integration-config-hocon-mp
+ Helidon Tests Integration for HOCON/JSON Config on MP
+ Validation for HOCON/JSON Config on MP
+
+
+
+ io.helidon.config
+ helidon-config-hocon-mp
+ test
+
+
+ io.helidon.microprofile.server
+ helidon-microprofile-server
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ test
+
+
+ io.helidon.microprofile.tests
+ helidon-microprofile-tests-junit5
+ test
+
+
+
diff --git a/tests/integration/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/ConfigBean.java b/tests/integration/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/ConfigBean.java
new file mode 100644
index 00000000000..ab75b3b3a2e
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/ConfigBean.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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.
+ * 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.hocon.mp;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import javax.inject.Inject;
+
+public class ConfigBean {
+ // Main Hocon config file properties
+ @Inject
+ @ConfigProperty(name = "hocon.string")
+ public String hocon_string;
+
+ @Inject
+ @ConfigProperty(name = "hocon.number")
+ public int hocon_number;
+
+ @Inject
+ @ConfigProperty(name = "hocon.array.0")
+ public String hocon_array_0;
+
+ @Inject
+ @ConfigProperty(name = "hocon.array.1")
+ public String hocon_array_1;
+
+ @Inject
+ @ConfigProperty(name = "hocon.array.2")
+ public String hocon_array_2;
+
+ @Inject
+ @ConfigProperty(name = "hocon.boolean")
+ public boolean hocon_boolean;
+
+ // Include properties
+ @Inject
+ @ConfigProperty(name = "hocon_include.string")
+ public String hocon_include_string;
+
+ @Inject
+ @ConfigProperty(name = "hocon_include.number")
+ public int hocon_include_number;
+
+ @Inject
+ @ConfigProperty(name = "hocon_include.array.0")
+ public String hocon_include_array_0;
+
+ @Inject
+ @ConfigProperty(name = "hocon_include.array.1")
+ public String hocon_include_array_1;
+
+ @Inject
+ @ConfigProperty(name = "hocon_include.array.2")
+ public String hocon_include_array_2;
+
+ @Inject
+ @ConfigProperty(name = "hocon_include.boolean")
+ public boolean hocon_include_boolean;
+
+ // Json config file properties
+ @Inject
+ @ConfigProperty(name = "json.string")
+ public String json_string;
+
+ @Inject
+ @ConfigProperty(name = "json.number")
+ public int json_number;
+
+ @Inject
+ @ConfigProperty(name = "json.array.0")
+ public String json_array_0;
+
+ @Inject
+ @ConfigProperty(name = "json.array.1")
+ public String json_array_1;
+
+ @Inject
+ @ConfigProperty(name = "json.array.2")
+ public String json_array_2;
+
+ @Inject
+ @ConfigProperty(name = "json.boolean")
+ public boolean json_boolean;
+}
diff --git a/tests/integration/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpMetaConfigTest.java b/tests/integration/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpMetaConfigTest.java
new file mode 100644
index 00000000000..1c133901c4f
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/java/io/helidon/config/hocon/mp/HoconJsonMpMetaConfigTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 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.
+ * 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.hocon.mp;
+
+import io.helidon.microprofile.config.ConfigCdiExtension;
+import io.helidon.microprofile.server.JaxRsCdiExtension;
+import io.helidon.microprofile.server.ServerCdiExtension;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import javax.enterprise.inject.se.SeContainer;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.CDI;
+
+/**
+ * Test meta-config on MP with HOCON and JSON parsing.
+ *
+ * This will use SeContainerInitializer rather than @HelidonTest as the latter does not make meta-config work
+ */
+public class HoconJsonMpMetaConfigTest {
+ private static ConfigBean bean;
+ private static SeContainer container;
+
+ @BeforeAll
+ static void initialize() {
+ System.setProperty("io.helidon.config.mp.meta-config", "custom-mp-meta-config.yaml");
+ System.setProperty("mp.initializer.allow", "true");
+ System.setProperty("mp.initializer.no-warn", "true");
+
+ container = SeContainerInitializer.newInstance()
+ .disableDiscovery()
+ .addExtensions(ConfigCdiExtension.class, ServerCdiExtension.class, JaxRsCdiExtension.class)
+ .addBeanClasses(ConfigBean.class)
+ .initialize();
+
+ bean = CDI.current()
+ .select(ConfigBean.class)
+ .get();
+ }
+
+ @AfterAll
+ static void destroy() {
+ System.clearProperty("io.helidon.config.mp.meta-config");
+ System.clearProperty("mp.initializer.allow");
+ System.clearProperty("mp.initializer.no-warn");
+ container.close();
+ }
+
+ @Test
+ void TestHoconConfig() {
+ Assertions.assertEquals(bean.hocon_string, "Meta String");
+ Assertions.assertEquals(bean.hocon_number, 20);
+ Assertions.assertEquals(bean.hocon_array_0, "Meta Array 1");
+ Assertions.assertEquals(bean.hocon_array_1, "Meta Array 2");
+ Assertions.assertEquals(bean.hocon_array_2, "Meta Array 3");
+ Assertions.assertTrue(bean.hocon_boolean);
+ }
+
+ @Test
+ void TestHoconIncludeConfig() {
+ Assertions.assertEquals(bean.hocon_include_string, "Meta Include String");
+ Assertions.assertEquals(bean.hocon_include_number, 10);
+ Assertions.assertEquals(bean.hocon_include_array_0, "Meta Include Array 1");
+ Assertions.assertEquals(bean.hocon_include_array_1, "Meta Include Array 2");
+ Assertions.assertEquals(bean.hocon_include_array_2, "Meta Include Array 3");
+ Assertions.assertFalse(bean.hocon_include_boolean);
+ }
+
+ @Test
+ void TestJsonConfig() {
+ Assertions.assertEquals(bean.json_string, "Meta String");
+ Assertions.assertEquals(bean.json_number, 20);
+ Assertions.assertEquals(bean.json_array_0, "Meta Array 1");
+ Assertions.assertEquals(bean.json_array_1, "Meta Array 2");
+ Assertions.assertEquals(bean.json_array_2, "Meta Array 3");
+ Assertions.assertTrue(bean.json_boolean);
+ }
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/application-dev.conf b/tests/integration/config/hocon-mp/src/test/resources/application-dev.conf
new file mode 100644
index 00000000000..75f578a2ca7
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/application-dev.conf
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+include "include-dev.conf"
+
+hocon = {
+ string = "Overriden String"
+ array = [
+ "Overriden Array 1"
+ "Overriden Array 2"
+ "Overriden Array 3"
+ ]
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/application-dev.json b/tests/integration/config/hocon-mp/src/test/resources/application-dev.json
new file mode 100644
index 00000000000..d29ef2d5138
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/application-dev.json
@@ -0,0 +1,10 @@
+{
+ "json": {
+ "string": "Overriden String",
+ "array": [
+ "Overriden Array 1",
+ "Overriden Array 2",
+ "Overriden Array 3"
+ ]
+ }
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/application.conf b/tests/integration/config/hocon-mp/src/test/resources/application.conf
new file mode 100644
index 00000000000..1ca37739357
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/application.conf
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+include "include.conf"
+
+hocon = {
+ string = "String"
+ number = 10
+ array = [
+ "Array 1"
+ "Array 2"
+ "Array 3"
+ ]
+ boolean = true
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/application.json b/tests/integration/config/hocon-mp/src/test/resources/application.json
new file mode 100644
index 00000000000..5979a65e88b
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/application.json
@@ -0,0 +1,12 @@
+{
+ "json": {
+ "string": "String",
+ "number": 10,
+ "array": [
+ "Array 1",
+ "Array 2",
+ "Array 3"
+ ],
+ "boolean": true
+ }
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/custom-mp-meta-config.yaml b/tests/integration/config/hocon-mp/src/test/resources/custom-mp-meta-config.yaml
new file mode 100644
index 00000000000..74ad4a8de37
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/custom-mp-meta-config.yaml
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+sources:
+ - type: "environment-variables"
+ - type: "system-properties"
+ - type: "hocon"
+ classpath: "meta-application.conf"
+ optional: false
+ - type: "json"
+ classpath: "meta-application.json"
+ optional: false
diff --git a/tests/integration/config/hocon-mp/src/test/resources/include-dev.conf b/tests/integration/config/hocon-mp/src/test/resources/include-dev.conf
new file mode 100644
index 00000000000..32d5814b1ee
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/include-dev.conf
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+hocon_include {
+ string = "Include String"
+ number = 20
+ array = [
+ "Include Array 1"
+ "Include Array 2"
+ "Include Array 3"
+ ]
+ boolean = false
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/include.conf b/tests/integration/config/hocon-mp/src/test/resources/include.conf
new file mode 100644
index 00000000000..32d5814b1ee
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/include.conf
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+hocon_include {
+ string = "Include String"
+ number = 20
+ array = [
+ "Include Array 1"
+ "Include Array 2"
+ "Include Array 3"
+ ]
+ boolean = false
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/meta-application.conf b/tests/integration/config/hocon-mp/src/test/resources/meta-application.conf
new file mode 100644
index 00000000000..fa8887cf167
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/meta-application.conf
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+include "meta-include.conf"
+
+hocon = {
+ string = "Meta String"
+ number = 20
+ array = [
+ "Meta Array 1"
+ "Meta Array 2"
+ "Meta Array 3"
+ ]
+ boolean = true
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/meta-application.json b/tests/integration/config/hocon-mp/src/test/resources/meta-application.json
new file mode 100644
index 00000000000..5b63c1a109a
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/meta-application.json
@@ -0,0 +1,12 @@
+{
+ "json": {
+ "string": "Meta String",
+ "number": 20,
+ "array": [
+ "Meta Array 1",
+ "Meta Array 2",
+ "Meta Array 3"
+ ],
+ "boolean": true
+ }
+}
diff --git a/tests/integration/config/hocon-mp/src/test/resources/meta-include.conf b/tests/integration/config/hocon-mp/src/test/resources/meta-include.conf
new file mode 100644
index 00000000000..c7859215156
--- /dev/null
+++ b/tests/integration/config/hocon-mp/src/test/resources/meta-include.conf
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 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.
+# 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.
+#
+
+hocon_include {
+ string = "Meta Include String"
+ number = 10
+ array = [
+ "Meta Include Array 1"
+ "Meta Include Array 2"
+ "Meta Include Array 3"
+ ]
+ boolean = false
+}
diff --git a/tests/integration/config/pom.xml b/tests/integration/config/pom.xml
index 9d94061f88d..b232c291f8e 100644
--- a/tests/integration/config/pom.xml
+++ b/tests/integration/config/pom.xml
@@ -37,5 +37,6 @@
gh-2171
gh-2171-yml
+ hocon-mp
-
\ No newline at end of file
+