////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Configuring Your Application

include::./attributes.adoc[]

Hardcoded values in your code are a _no go_ (even if we all did it at some point ;-)).
In this guide, we learn how to configure your application.

== Prerequisites

To complete this guide, you need:

* between 5 and 10 minutes
* an IDE
* JDK 1.8+ installed with `JAVA_HOME` configured appropriately
* Apache Maven 3.5.3+

== Solution

We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone {quickstarts-clone-url}`, or download an {quickstarts-archive-url}[archive].

The solution is located in the `config-quickstart` {quickstarts-tree-url}/config-quickstart[directory].

== Creating the Maven project

First, we need a new project. Create a new project with the following command:

[source,shell,subs=attributes+]
----
mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=config-quickstart \
    -DclassName="org.acme.config.GreetingResource" \
    -Dpath="/greeting"
cd config-quickstart
----

It generates:

* the Maven structure
* a landing page accessible on `http://localhost:8080`
* example `Dockerfile` files for both `native` and `jvm` modes
* the application configuration file
* an `org.acme.config.GreetingResource` resource
* an associated test

== Injecting configuration value

Quarkus uses https://microprofile.io/project/eclipse/microprofile-config[MicroProfile Config] to inject the configuration in the application.
The injection uses the `@ConfigProperty` annotation.

[source,java]
----
@ConfigProperty(name = "greeting.message")
String message;
----

NOTE: When injecting a configured value, you can use `@Inject @ConfigProperty` or just `@ConfigProperty`.
The `@Inject` annotation is not necessary for members annotated with `@ConfigProperty`, a behavior which differs from https://microprofile.io/project/eclipse/microprofile-config[MicroProfile Config]

Edit the `org.acme.config.GreetingResource`, and introduce the following configuration properties:

[source,java]
----
@ConfigProperty(name = "greeting.message") <1>
String message;

@ConfigProperty(name = "greeting.suffix", defaultValue="!") <2>
String suffix;

@ConfigProperty(name = "greeting.name")
Optional<String> name; <3>
----
<1> If you do not provide a value for this property, the application startup fails with `javax.enterprise.inject.spi.DeploymentException: No config value of type [class java.lang.String] exists for: greeting.message`.
<2> The default value is injected if the configuration does not provide a value for `greeting.suffix`.
<3> This property is optional - an empty `Optional` is injected if the configuration does not provide a value for `greeting.name`.

Now, modify the `hello` method to use the injected properties:

[source,java]
----
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
    return message + " " + name.orElse("world") + suffix;
}
----


== Create the configuration

By default, Quarkus reads `application.properties`.
Edit the `src/main/resources/application.properties` with the following content:

[source,shell]
----
# Your configuration properties
greeting.message = hello
greeting.name = quarkus
----

Once set, check the application with:

[source,shell]
----
$ curl http://localhost:8080/greeting
hello quarkus!
----

TIP: If the application requires configuration values and these values are not set, an error is thrown.
So you can quickly know when your configuration is complete.

== Update the test

We also need to update the functional test to reflect the changes made to the endpoint.
Edit the `src/test/java/org/acme/config/GreetingResourceTest.java` file and change the content of the `testHelloEndpoint` method to:


[source,java]
----
package org.acme.config;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/greeting")
          .then()
             .statusCode(200)
             .body(is("hello quarkus!")); // Modified line
    }

}
----

== Package and run the application

Run the application with: `./mvnw compile quarkus:dev`.
Open your browser to http://localhost:8080/greeting.

Changing the configuration file is immediately reflected.
You can add the `greeting.suffix`, remove the other properties, change the values, etc.

As usual, the application can be packaged using `./mvnw clean package` and executed using the `-runner.jar` file.
You can also generate the native executable with `./mvnw clean package -Pnative`.

== Using @ConfigProperties

As an alternative to injecting multiple related configuration values in the way that was shown in the previous example,
users can also use the `@io.quarkus.arc.config.ConfigProperties` annotation to group these properties together.

For the greeting properties above, a `GreetingConfiguration` class could be created like so:

[source,java]
----
package org.acme.config;

import io.quarkus.arc.config.ConfigProperties;
import java.util.Optional;

@ConfigProperties(prefix = "greeting") <1>
public class GreetingConfiguration {

    private String message;
    private String suffix = "!"; <2>
    private Optional<String> name;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public Optional<String> getName() {
        return name;
    }

    public void setName(Optional<String> name) {
        this.name = name;
    }
}
----
<1> `prefix` is optional. If not set then the prefix to be used will be determined by the class name. In this case it would still be `greeting` (since the `Configuration` suffix is removed). If the class were named `GreetingExtraConfiguration` then the resulting default prefix would be `greeting-extra`.
<2> `!` will be the default value if `greeting.suffix` is not set

This class could then be injected into the `GreetingResource` using the familiar CDI `@Inject` annotation like so:

[source,java]
----
@Inject
GreetingConfiguration greetingConfiguration;
----

Another alternative style provided by Quarkus is to create `GreetingConfiguration` as an interface like so:

[source,java]
----
package org.acme.config;

import io.quarkus.arc.config.ConfigProperties;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.Optional;

@ConfigProperties(prefix = "greeting")
public interface GreetingConfiguration {

    @ConfigProperty(name = "message") <1>
    String message();

    @ConfigProperty(defaultValue = "!")
    String getSuffix(); <2>

    Optional<String> getName(); <3>
}
----
<1> The `@ConfigProperty` annotation is needed because the name of the configuration property that the method corresponds to doesn't follow the getter method naming conventions
<2> In this case since `name` was not set, the corresponding property will be `greeting.suffix`.
<3> It is unnecessary to specify the `@ConfigProperty` annotation because the method name follows the getter method naming conventions (`greeting.name` being the corresponding property) and no default value is needed.

When using `@ConfigProperties` on a class or an interface, if the value of one of its fields is not provided, the application startup will fail and a `javax.enterprise.inject.spi.DeploymentException` indicating the missing value information will be thrown.
This does not apply to `Optional` fields and fields with a default value.

=== Additional notes on @ConfigProperties

When using a regular class annotated with `@ConfigProperties` the class doesn't necessarily have to declare getters and setters.
Having simple public non-final fields is valid as well.

Furthermore the configuration classes support nested object configuration. Suppose there was a need to have an extra layer
of greeting configuration named `hidden` that would contain a few fields. This could be achieved like so:

[source,java]
----
@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {

    public String message;
    public String suffix = "!";
    public Optional<String> name;
    public HiddenConfig hidden; <1>

    public static class HiddenConfig {
        public Integer prizeAmount;
        public List<String> recipients;
    }
}
----
<1> The name of the field (not the class name) will determine the name of the properties that are bound to the object.

Setting the properties would occur in the normal manner, for example in `application.properties` one could have:

[source,properties]
----
greeting.message = hello
greeting.name = quarkus
greeting.hidden.prizeAmount=10
greeting.hidden.recipients=Jane,John
----

Furthermore, classes annotated with `@ConfigProperties` can be annotated with Bean Validation annotations similar to the following example:

[source,java]
----
@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {

    @Size(min = 20)
    public String message;
    public String suffix = "!";

}
----

If the validation fails with the given configuration, the application will fail to start and indicate the corresponding validation errors in the log.

In the case of an interface being annotated with `@ConfigProperties`, the interface is allowed to extend other interfaces and methods from
the entire interface hierarchy are used to bind properties.

== Configuring Quarkus

Quarkus itself is configured via the same mechanism as your application. Quarkus reserves the `quarkus.` namespace
for its own configuration. For example to configure the HTTP server port you can set `quarkus.http.port` in
`application.properties`.

[IMPORTANT]
====
As mentioned above, properties prefixed with `quarkus.` are effectively reserved for configuring Quarkus itself and
therefore `quarkus.`should **never** be used as prefix for application specific properties.

In the previous examples using `quarkus.message` instead of `greeting.message` would result in unexpected behavior.
====

=== List of all configuration properties

All the Quarkus configuration properties are link:all-config[documented and searcheable].

=== Generating configuration for your application

It is also possible to generate an example `application.properties` with all known configuration properties, to make
it easy to see what Quarkus configuration options are available. To do this, run:

[source,shell]
--
./mvnw quarkus:generate-config
--

This will create a `src/main/resources/application.properties.example` file that contains all the config options
exposed via the extensions you currently have installed. These options are commented out, and have their default value
when applicable. For example this HTTP port config entry will appear as:


[source,properties]
--
#
# The HTTP port
#
#quarkus.http.port=8080
--

Rather than generating an example config file, you can also add these to you actual config file by setting the `-Dfile`
parameter:

[source,shell]
--
./mvnw quarkus:generate-config -Dfile=application.properties
--

If a config option is already present (commented or not) it will not be added, so it is safe to run this after
adding an additional extension to see what additional options have been added.

== Overriding properties at runtime

Quarkus does much of its configuration and bootstrap at build time.
Most properties will then be read and set during the build time step.
To change them, make sure to repackage your application.

[source,shell]
--
./mvnw clean package
--

Extensions do define _some_ properties as overridable at runtime.
A canonical example is the database URL, username and password which is only known specifically in your target environment.
This is a tradeoff as the more runtime properties are available, the less build time prework Quarkus can do. The list of runtime properties is therefore lean.

You can override these runtime properties with the following mechanisms (in decreasing priority):

1. using system properties:
  * for a runner jar: `java -Dquarkus.datasource.password=youshallnotpass -jar target/myapp-runner.jar`
  * for a native executable: `./target/myapp-runner -Dquarkus.datasource.password=youshallnotpass`
2. using environment variables:
  * for a runner jar: `export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ; java -jar target/myapp-runner.jar`
  * for a native executable: `export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ; ./target/myapp-runner`
3. using a configuration file placed in `$PWD/config/application.properties`
  * By placing an `application.properties` file inside a directory named `config` which resides in the directory where the application runs, any runtime properties defined
in that file will override the default configuration. Furthermore any runtime properties added to this file that were not part of the original `application.properties` file
_will also_ be taken into account.
  * This works in the same way for runner jar and the native executable

NOTE: Environment variables names are following the conversion rules of link:https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#default-configsources[Eclipse MicroProfile]

NOTE: The `config/application.properties` features is available in development mode as well. To make use of it, `config/application.properties` needs to be placed inside the build tool's output directory (`target` for Maven and `build` for Gradle).
Keep in mind however that any cleaning operation from the build tool like `mvn clean` or `gradle clean` will remove the `config` directory as well.

=== Configuration Profiles

Quarkus supports the notion of configuration profiles. These allow you to have multiple configuration in the same file and
select between them via a profile name.

The syntax for this is `%{profile}.config.key=value`. For example if I have the following:

[source,properties]
----
quarkus.http.port=9090
%dev.quarkus.http.port=8181
----

The Quarkus HTTP port will be 9090, unless the `dev` profile is active, in which case it will be 8181.

By default Quarkus has three profiles, although it is possible to use as many as you like. The default profiles are:

* *dev* - Activated when in development mode (i.e. `quarkus:dev`)
* *test* - Activated when running tests
* *prod* - The default profile when not running in development or test mode

There are two ways to set a custom profile, either via the `quarkus.profile` system property or the `QUARKUS_PROFILE`
environment variable. If both are set the system property takes precedence. Note that it is not necessary to
define the names of these profiles anywhere, all that is necessary is to create a config property with the profile
name, and then set the current profile to that name. For example if I want a `staging` profile with a different HTTP port
I can add the following to `application.properties`:

[source,properties]
----
quarkus.http.port=9090
%staging.quarkus.http.port=9999
----

And then set the `QUARKUS_PROFILE` environment variable to `staging` to activate my profile.

==== Miscellaneous
The default Quarkus application runtime profile is set to the profile used to build the application.
For example:
[source,shell]
----
./mvnw package -Pnative -Dquarkus.profile=prod-aws`
./target/my-app-1.0-runner // <1>
----
<1> The command will run with the `prod-aws` profile. This can be overridden using the `quarkus.profile` system property.

== Custom Configuration

=== Custom configuration sources

You can also introduce custom configuration sources in the standard MicroProfile Config manner.  To
do this, you must provide a class which implements either `org.eclipse.microprofile.config.spi.ConfigSource`
or `org.eclipse.microprofile.config.spi.ConfigSourceProvider`.  Create a
https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html[service file] for the
class and it will be detected and installed at application startup.

=== Custom configuration converters

You can also use your custom types as a configuration values. This can be done by implementing `org.eclipse.microprofile.config.spi.Converter<T>`
and adding its fully qualified class name in the `META-INF/services/org.eclipse.microprofile.config.spi.Converter` file.

Let us assume you have a custom type like this one:

[source,java]
----
package org.acme.config;

public class MicroProfileCustomValue {

    private final int number;

    public MicroProfileCustomValue(int number) {
        this.number = number;
    };

    public int getNumber() {
        return number;
    }
}
----

The corresponding converter will look like the one below. Please note that your custom converter class must be `public` and must have
a `public` no-argument constructor. It also must not be `abstract`.


[source,java]
----
package org.acme.config;

import org.eclipse.microprofile.config.spi.Converter;

public class MicroProfileCustomValueConverter implements Converter<MicroProfileCustomValue> {

    @Override
    public MicroProfileCustomValue convert(String value) {
        return new MicroProfileCustomValue(Integer.valueOf(value));
    }
}
----

Then you need to include the fully qualified class name of the converter in a service file `META-INF/services/org.eclipse.microprofile.config.spi.Converter`.
If you have more converters, simply add their class names in this file as well. Single fully qualified class name per line, for example:

[source]
----
org.acme.config.MicroProfileCustomValueConverter
org.acme.config.SomeOtherConverter
org.acme.config.YetAnotherConverter
----

Please note that `SomeOtherConverter` and `YetAnotherConverter` were added just for a demonstration. If you include in this file classes
which are not available at runtime, the converters loading will fail.

After this is done you can use your custom type as a configuration value:

[source,java]
----
@ConfigProperty(name = "configuration.value.name")
MicroProfileCustomValue value;
----

==== Converter priority

In some cases, you may want to use a custom converter to convert a type which is already converted
by a different converter. In such cases, you can use the `javax.annotation.Priority` annotation to
change converters precedence and make your custom converter of higher priority than the other
on the list.

By default, if no `@Priority` can be found on a converter, it's registered with a priority of 100
and all Quarkus core converters are registered with a priority of 200, so depending on which
converter you would like to replace, you need to set a higher value.

To demonstrate the idea let us implement a custom converter which will take precedence over
`MicroProfileCustomValueConverter` implemented in the previous example.

[source,java]
----
package org.acme.config;

import javax.annotation.Priority;
import org.eclipse.microprofile.config.spi.Converter;

@Priority(150)
public class MyCustomConverter implements Converter<MicroProfileCustomValue> {

    @Override
    public MicroProfileCustomValue convert(String value) {

        final int secretNumber;
        if (value.startsFrom("OBF:")) {
            secretNumber = Integer.valueOf(SecretDecoder.decode(value));
        } else {
            secretNumber = Integer.valueOf(value);
        }

        return new MicroProfileCustomValue(secretNumber);
    }
}
----

Since it converts the same value type (namely `MicroProfileCustomValue`) and has a priority
of 150, it will be used instead of a `MicroProfileCustomValueConverter` which has a default
priority of 100.

NOTE: This new converter also needs to be listed in a service file, i.e. `META-INF/services/org.eclipse.microprofile.config.spi.Converter`.

== More info on how to configure

Quarkus relies on Eclipse MicroProfile and inherits its features.

There are converters that convert your property file content from `String` to typed Java types. See the list link:https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/converters.asciidoc[in the specification].

// TODO: make Ken review this section and discuss SmallRye expansion.
