
///////////////////////////////////////////////////////////////////////////////

    Copyright (c) 2020 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.

///////////////////////////////////////////////////////////////////////////////

= MicroProfile Config
:toc:
:toc-placement: preamble
:spec-name: MicroProfile Config
:description: {spec-name} support in Helidon MP
:keywords: helidon, mp, microprofile, config, encryption, reference
:h1Prefix: MP

== About {spec-name}
Helidon MicroProfile Config is an implementation of https://github.com/eclipse/microprofile-config/[Eclipse MicroProfile Config].
You can configure your applications using MicroProfile's config configuration sources and APIs.

You can also extend the configuration using MicroProfile SPI to add custom `ConfigSource` and `Converter` by implementing the
`org.eclipse.microprofile.config.spi.ConfigSource` and `org.eclipse.microprofile.config.spi.Converter` interfaces respectively.

=== {spec-name} Features
{spec-name} uses `ConfigSource` SPI to load configuration data, either from default configuration sources such
file `META-INF/microprofile-config.properties`, environment variables, and system properties; or from custom `ConfigSource`
located by Java Service Loader.

The data is then available through {spec-name} APIs to be injected into CDI Beans, or to be obtained using a `Config`
instance programmatically.

{spec-name} provides typed access to configuration values, using built-in converters, and `Converter` implementations located
by Java Service Loader.

==== Using {spec-name} API

You can use MicroProfile Config API to get configuration properties by using `ConfigProvider.getConfig()`
or injecting configuration values with `@ConfigProperty`.

[source=java]
.Using ConfigProvider.getConfig()
----
org.eclipse.microprofile.config.Config config = ConfigProvider.getConfig();
config.getOptionalValue("app.greeting", String.class).orElse("Hello");
----

[source=java]
.Injecting configured properties into a constructor
----
@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting", defaultValue = "Hello") String message) {
    this.message = message
}
----

==== {spec-name} Config Sources

The example below shows how the MicroProfile configuration file `microprofile-config.properties` can be used to modify the server listen port property.

----
// Application properties. This is the default greeting
app.greeting=Hello

// Microprofile server properties
server.port=8080
server.host=0.0.0.0
----

=== Helidon {spec-name} Features

Helidon MicroProfile Config offers the following features on top of the specification:

* *References* +
You can use `${reference}` to reference another configuration key in a key value. This
allows to configure a single key to be reused in multiple other keys.

[source=yaml]
.Example
----
uri: "http://localhost:8080"
service-1: "${uri}/service1"
service-2: "${uri}/service2"
----


* *Encryption* +
You can encrypt secrets using a master password and store them in a configuration file.
The config encryption filter in MicroProfile Config is enabled by default.
For more information, see <<about/02_configuration-secrets.adoc,Configuration Secrets>>.

[source=properties]
.Example of encrypted secrets
----
# Password encrypted using a master password
client_secret=${GCM=mYRkg+4Q4hua1kvpCCI2hg==}
# Password encrypted using public key (there are length limits when using RSA)
client_secret=${RSA=mYRkg+4Q4hua1kvpCCI2hg==}
# Password in clear text, can be used in development
# The system needs to be configured to accept clear text
client_secret=${CLEAR=known_password}
----

* *Meta Configuration* +
You can configure the Config using Helidon SE Config meta configuration feature.
When used, the {spec-name} uses a single configuration source - Helidon SE Config configured
from meta configuration.

The meta-config allows configuration of config sources and other configuration options,
including retry policies and polling strategies.

If a file named `meta-config.yaml`, or `meta-config.properties` is in the current directory or
on the classpath and there is no explicit setup of `Config` in the code, the configuration will
be loaded from the `meta-config` file.

[source=yaml]
.Example of a YAML meta configuration file:
----
sources:
  - type: "system-properties" <1>
  - type: "environment-variables" <2>
  - type: "file"
    properties:
      optional: true
      path: "mp-config.yaml" <3>
  - type: "classpath"
    properties:
      optional: true
      resource: application.yaml <4>
  - type: "classpath"
      multi-source: true
    properties:
      resource: "META-INF/microprofile-config.properties" <5>
----

<1> Loads the environment variables config source.
<2> Loads the system variables config source.
<3> Loads the file config source from `mp-config.yaml` that is optional.
<4> Loads the file config source from `application.yaml` that is optional.
<5> Loads the classpath resource config source for  `microprofile-config.properties` that is the default configuration source of Microprofile application and is mandatory.


== Guides

[PILLARS]
====
[CARD]
.MP Config Guide
[link=mp/guides/03_config.adoc]
--
Step-by-step guide about using {spec-name} in your Helidon MP application.
--
====

== Using MicroProfile Config Sources

The following configuration sources can be used to retrieve the configuration:

[cols="3,5"]
|===
|Source |Description

|System properties   |A mutable source that uses `System.getProperties()` to obtain configuration values.

|Environment variables   |An immutable source that uses `System.env()` to obtain configuration values and resolves aliases as defined by the MicroProfile Config specification.

|`META-INF/microprofile-config.properties`   |The properties config source as defined by MicroProfile Config specification.

|`application.yaml`    |The Helidon default configuration source.

|File    |Creates the source from a properties file on the file system with `MpConfigSources.create(Path)`.

|URL    |Creates the source from properties from an URL with `MpConfigSources.create(URL)`.

|`Map<String, String>`   |Creates the source from a Map with `MpConfigSources.create(Map)`.

|`Properties`    |Creates the source directly from Properties with `MpConfigSources.create(Properties)`.

|File on classpath    |Creates the source from a properties file on classpath with `MpConfigSources.classpath(String)`.

|YAML    |Creates the source from YAML using `YamlMpConfigSource.create(Path)` or `YamlMpConfigSource.create(URL)`.

|===

== Using Helidon Config APIs

You can use `MpConfigSources.create(helidonConfig)` to create a config source from Helidon config and then use it to create a MicroProfile instance.

----
io.helidon.config.Config helidonConfig = io.helidon.config.Config.builder()
                .addSource(ConfigSources.create(Map.of("key", "value"))) <1>
                .build();

Config config = ConfigProviderResolver.instance()
                .getBuilder()
                .withSources(MpConfigSources.create(helidonConfig)) <2>
                .build();
----

<1> Creates a config source from Helidon Config.
<2> Creates a MicroProfile Config instance.

For more information on using Helidon Config APIs, see the Helidon SE Configuration documentation.

== Additional Information

- https://helidon.io/docs/latest/apidocs/io/helidon/config/spi/package-summary.html[Helidon Config SPI]
- https://helidon.io/docs/latest/apidocs/io/helidon/config/package-summary.html[Helidon Config API]
- https://download.eclipse.org/microprofile/microprofile-config-1.3/apidocs/[Eclispe MicroProfile API]
