Configuring your Quarkus applications

Guide
  • Red Hat build of Quarkus 2.2
  • Updated 23 February 2022
  • Published 22 February 2022

Configuring your Quarkus applications

Guide
Red Hat build of Quarkus 2.2
  • Updated 23 February 2022
  • Published 22 February 2022

This guide describes how to configure your Quarkus application. You can configure your Quarkus application by using either of the following methods:

  • Setting properties in the application.properties file

  • Applying structured configuration in YAML format by updating the application.yaml file

This guide also describes how you can extend and customize the configuration for your application by doing the following:

  • Substituting and composing configuration property values using property expressions

  • Implementing MicroProfile-compliant classes with custom configuration source converters that read configuration values from different external sources

  • Using configuration profiles to maintain separate sets of configuration values for your development, test, and production environments

The procedures include configuration examples that are created by using the Quarkus config-quickstart exercise.

Prerequisites
  • Have OpenJDK (JDK) 11 or 17 installed and the JAVA_HOME environment variable set to specify the location of the Java SDK.

    • Log in to the Red Hat Customer Portal to download the Red Hat build of Open JDK from the Software Downloads page.

  • Have Apache Maven 3.8.1 or higher installed.

  • Have Maven configured to use artifacts from the Quarkus Maven repository.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. Because of the enormity of this endeavor, these changes will be implemented gradually over several upcoming releases. For more details, see our CTO Chris Wright’s message.

1. Red Hat build of Quarkus configuration options

Configuration options enable you to change the settings of your application in a single configuration file. Red Hat build of Quarkus supports configuration profiles that you can use to group related properties and switch between profiles as required.

By default, Quarkus reads properties from the application.properties file located in the src/main/resources directory.

By adding the config-yaml dependency to your project pom.xml file, you can add your application properties in the application.yaml file using the YAML format. For more information, see Adding YAML configuration support.

Red Hat build of Quarkus also supports MicroProfile Config, which enables you to load the configuration of your application from other sources.

You can use the MicroProfile Config specification from the Eclipse MicroProfile project to inject configuration properties into your application and configure them using a method defined in your code.

Quarkus can also read application properties from different origins, including the following sources:

  • The file system

  • A database

  • A Kubernetes or OpenShift ConfigMap object

  • Any source that can be loaded by a Java application

2. Creating the configuration quickstart project

With the config-quickstart project, you can get up and running with a simple Quarkus application using Apache Maven and the Quarkus Maven plug-in. The following procedure demonstrates how you can create a Quarkus Maven project.

Procedure
  1. Verify that Maven is using JDK 11 and that the Maven version is 3.8.1 or higher:

    mvn --version

    If this command does not return JDK 11, ensure that the directory where JDK 11 is installed on your system is included in the PATH environment variable:

    export PATH=$PATH:/path/to/jdk-11
  2. Enter the following command to generate the project:

    mvn com.redhat.quarkus.platform:quarkus-maven-plugin:2.2.5.Final-redhat-00007:create \
        -DprojectGroupId=org.acme \
        -DprojectArtifactId=config-quickstart \
        -DplatformGroupId=com.redhat.quarkus.platform \
        -DplatformVersion=2.2.5.Final-redhat-00007 \
        -DclassName="org.acme.config.GreetingResource" \
        -Dpath="/greeting"
    cd config-quickstart
    Verification

    This command creates the following items in the config-quickstart directory:

    • The Maven project directory structure

    • An org.acme.config.GreetingResource resource

    • A landing page that you can access at http://localhost:8080 after you start the application

    • Associated unit tests for testing your application in native mode and JVM mode

    • Example Dockerfile.jvm and Dockerfile.native files in the src/main/docker subdirectory

    • The application configuration file

    Alternatively, you can download a Quarkus Maven project to use in this tutorial from the Quarkus quickstart archive or clone the Quarkus Quickstarts Git repository. The exercise is located in the config-quickstart directory.

3. Injecting configuration values into your Quarkus application

Red Hat build of Quarkus uses the MicroProfile Config feature to inject configuration data into the application. You can access the configuration either through context and dependency injection (CDI) or by using a method that is defined in your code.

Use the @ConfigProperty annotation to map an object property to a key in the MicroProfile Config Sources file of your application.

The following procedure shows how you can inject an individual property configuration into a Quarkus config-quickstart project. The procedure and examples use the application.properties file configuration method.

Prerequisites
  • You have created the Quarkus config-quickstart project.

Procedure
  1. Open the src/main/resources/application.properties file.

  2. Add configuration properties to your configuration file where <property_name> is the property name and <value> is the value of the property:

    <property_name>=<value>

    The following example shows how to set the values for the greeting.message and the greeting.name properties in the Quarkus config-quickstart project:

    src/main/resources/application.properties
    greeting.message = hello
    greeting.name = quarkus

    When you are configuring your applications, do not prefix application-specific properties with the string quarkus. The quarkus prefix is reserved for configuring Quarkus at the framework level. Using quarkus as a prefix for application-specific properties might lead to unexpected results when your application runs.

  3. Review the GreetingResource.java Java file in your project. The file contains the GreetingResource class with the hello() method that returns a message when you send an HTTP request on the /greeting endpoint:

    src/main/java/org/acme/config/GreetingResource.java
    import java.util.Optional;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import org.eclipse.microprofile.config.inject.ConfigProperty;
    
    @Path("/greeting")
    public class GreetingResource {
    
        String message;
        Optional<String> name;
        String suffix;
    
    
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String hello() {
            return message + " " + name.orElse("world") + suffix;
        }
    }

    In the example provided, the values of the message and name strings in the hello() method are unconfigured. The application fails to compile and run successfully in this state.

  4. Define the message, name, and suffix fields, and annotate them with @ConfigProperty, matching the values that you defined for the greeting.message and greeting.name properties. Use the @ConfigProperty annotation to inject the configuration value for each string, as shown in the following example:

    src/main/java/org/acme/config/GreetingResource.java
    import java.util.Optional;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import org.eclipse.microprofile.config.inject.ConfigProperty;
    
    @Path("/greeting")
    public class GreetingResource {
    
      @ConfigProperty(name = "greeting.message") 1
      String message;
    
      @ConfigProperty(name = "greeting.suffix", defaultValue="!") 2
      String suffix;
    
      @ConfigProperty(name = "greeting.name")
      Optional<String> name; 3
    
      @GET
      @Produces(MediaType.TEXT_PLAIN)
      public String hello() {
          return message + " " + name.orElse("world") + suffix;
       }
    }
    1. If you do not configure a value for the message string, the application will fail and throw the following exception: javax.enterprise.inject.spi.DeploymentException: Failed to load config value of type class java.lang.String for: greeting.message

    2. If you do not configure a value for the greeting.suffix, Quarkus resolves it to the default value.

    3. If you do not define the greeting.name property, the value of the name string is blank. Your application still runs even when this value is blank because you set the Optional parameter on the name string.

    To inject a configured value, you can use @ConfigProperty. You do not need to include the @Inject annotation for members that you annotate with @ConfigProperty.

  5. Compile and start your application in development mode:

    ./mvnw quarkus:dev
  6. Enter the following command in a new terminal window to verify that the endpoint returns the message:

    curl http://localhost:8080/greeting

    This command returns the following output:

    hello quarkus!
  7. To stop the application, press Ctrl+C.

4. Updating the functional test to validate configuration changes

Before you test the functionality of your application, you must update the functional test to reflect the changes that you made to the endpoint of your application. The following procedure shows how you can update your testHelloEndpoint method on the Quarkus config-quickstart project.

Procedure
  1. Open the GreetingResourceTest.java file.

  2. Update the content of the testHelloEndpoint method:

    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
        }
    
    }

5. Setting configuration properties

By default, Quarkus reads properties from the application.properties file that is located in the src/main/resources directory. If you change build properties, ensure that you repackage your application.

Quarkus configures most properties during build time. Extensions can define properties as overridable at run time, for example, the database URL, a user name, and a password, which can be specific to your target environment.

Prerequisites
  • You have a Quarkus Maven project.

Procedure
  1. To package your Quarkus project, enter the following command:

    ./mvnw clean package
  2. Use one of the following methods to set the configuration properties:

    • Setting system properties:

      Enter the following command, where <property_name> is the name of the configuration property that you want to add and <value> is the value of the property:

      java -D<property_name>=<value> -jar target/myapp-runner.jar

      For example, to set the value of the quarkus.datasource.password property, enter the following command:

      java -Dquarkus.datasource.password=youshallnotpass -jar target/myapp-runner.jar
    • Setting environment variables:

      Enter the following command, where <property_name> is the name of the configuration property that you want to set and <value> is the value of the property:

      export <property_name>=<value> ; java -jar target/myapp-runner.jar
      Environment variable names follow the conversion rules of Eclipse MicroProfile. Convert the name to upper case and replace any character that is not alphanumeric with an underscore ( _).
    • Using an environment file:

      Create an .env file in your current working directory and add configuration properties, where <PROPERTY_NAME> is the property name and <value> is the value of the property:

      <PROPERTY_NAME>=<value>
      For development mode, this file can be located in the root directory of your project, but it is recommended to not track the file in version control. If you create an .env file in the root directory of your project, you can define keys and values that the program reads as properties.
    • Using the application.properties file:

      Place the configuration file in the $PWD/config/application.properties directory where the application runs so that any runtime properties that are defined in that file will override the default configuration.

      You can also use the config/application.properties features in development mode. Place the config/application.properties file inside the target directory. Any cleaning operation from the build tool, for example, mvn clean, also removes the config directory.

6. Advanced Configuration Mapping

Information and examples are provided to help you with advanced configuration mapping use cases.

The following advanced mapping procedures are extensions specific to Red Hat build of Quarkus and are outside of the 'MicroProfile Config' specification.

6.1. Annotating an interface with @ConfigMapping

Instead of individually injecting multiple related configuration values, use the @io.smallrye.config.ConfigMapping annotation to group configuration properties. The following procedure demonstrates how you can use the @ConfigMapping annotation on the Quarkus config-quickstart project.

Prerequisites
  • You have created the Quarkus config-quickstart project.

  • You have defined the greeting.message and greeting.name properties in the application.properties file of your project.

Procedure
  1. Review the GreetingResource.java file in your project and ensure that it contains the contents that are shown in this example. To use the @ConfigPoperties annotation to inject configuration properties from another configuration source into this class, you must import the java.util.Optional and org.eclipse.microprofile.config.inject.ConfigProperty packages.

    src/main/java/org/acme/config/GreetingResource.java
    import java.util.Optional;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import org.eclipse.microprofile.config.inject.ConfigProperty;
    
    @Path("/greeting")
    public class GreetingResource {
    
        @ConfigProperty(name = "greeting.message")
        String message;
    
        @ConfigProperty(name = "greeting.suffix", defaultValue="!")
        String suffix;
    
        @ConfigProperty(name = "greeting.name")
        Optional<String> name;
    
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String hello() {
            return message + " " + name.orElse("world") + suffix;
        }
    }
  2. Create a GreetingConfiguration.java file in the src/main/java/org/acme/config directory. Add the import statements for ConfigMapping and Optional to the file:

    src/main/java/org/acme/config/GreetingConfiguration.java
    import io.smallrye.config.ConfigMapping;
    import io.smallrye.config.WithDefault;
    import java.util.Optional;
    
    @ConfigMapping(prefix = "greeting")
    public interface GreetingConfiguration {
        String message();
    
        @WithDefault("!")
        String suffix();
    
        Optional<String> name();
    }
    1. The prefix property is optional. For example, in this scenario, the prefix is greeting.

    2. If greeting.suffix is not set, ! is used as the default value.

  3. Inject the GreetingConfiguration instance into the GreetingResource class by using the @Inject annotation, as follows:

    This snippet replaces the three fields that are annotated with @ConfigProperty that are in the initial version of the config-quickstart project.

    src/main/java/org/acme/config/GreetingResource.java
    @Path("/greeting")
    public class GreetingResource {
    
        @Inject
        GreetingConfiguration config;
    
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String hello() {
            return config.message() + " " + config.name().orElse("world") + config.suffix();
        }
    }
  4. Compile and start your application in development mode:

    ./mvnw quarkus:dev
    If you do not provide values for the class properties, the application fails to compile and a io.smallrye.config.ConfigValidationException error is returned to indicate that a value is missing. This does not apply to fields that are optional or fields with a default value.
  5. To verify that the endpoint returns the message, enter the following command in a new terminal window:

    curl http://localhost:8080/greeting
  6. You receive the following message:

    hello quarkus!
  7. To stop the application, press Ctrl+C.

6.2. Using nested object configuration

You can define an interface that is nested inside another interface. This procedure demonstrates how to create and configure a nested interface in the Quarkus config-quickstart project.

Prerequisites
  • You have created the Quarkus config-quickstart project.

  • You have defined the greeting.message and greeting.name properties in the application.properties file of your project.

Procedure
  1. Review the GreetingResource.java in your project. The file contains the GreetingResource class with the hello() method that returns a message when you send an HTTP request on the /greeting endpoint:

    src/main/java/org/acme/config/GreetingResource.java
    import java.util.Optional;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import org.eclipse.microprofile.config.inject.ConfigProperty;
    
    @Path("/greeting")
    public class GreetingResource {
    
        @ConfigProperty(name = "greeting.message")
        String message;
    
        @ConfigProperty(name = "greeting.suffix", defaultValue="!")
        String suffix;
    
        @ConfigProperty(name = "greeting.name")
        Optional<String> name;
    
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String hello() {
            return message + " " + name.orElse("world") + suffix;
        }
    }
  2. Create a GreetingConfiguration.java class file with the GreetingConfiguration instance. This class contains the externalized configuration for the hello() method that is defined in the GreetingResource class:

    src/main/java/org/acme/config/GreetingConfiguration.java
    import io.smallrye.config.ConfigMapping;
    import io.smallrye.config.WithDefault;
    import java.util.Optional;
    
    @ConfigMapping(prefix = "greeting")
    public interface GreetingConfiguration {
        String message();
    
        @WithDefault("!")
        String suffix();
    
        Optional<String> name();
    }
  3. Create the ContentConfig class that is nested inside the GreetingConfiguration instance, as shown in the following example:

    src/main/java/org/acme/config/GreetingConfiguration.java
    import io.smallrye.config.ConfigMapping;
    import io.smallrye.config.WithDefault;
    
    import java.util.List;
    import java.util.Optional;
    
    @ConfigMapping(prefix = "greeting")
    public interface GreetingConfiguration {
        String message();
    
        @WithDefault("!")
        String suffix();
    
        Optional<String> name();
    
        ContentConfig content();
    
        interface ContentConfig {
            Integer prizeAmount();
    
            List<String> recipients();
        }
    }

    The method name of the ContentConfig class is content. To ensure that you bind the properties to the correct interface, when you define configuration properties for this class, use content in the prefix. Doing this can also prevent property name conflicts and unexpected application behavior.

  4. Define the greeting.content.prize-amount and greeting.content.recipients configuration properties in your application.properties file.

    The following example shows the properties defined for the GreetingConfiguration instance and the ContentConfig classes:

    src/main/resources/application.properties
    greeting.message = hello
    greeting.name = quarkus
    greeting.content.prize-amount=10
    greeting.content.recipients=Jane,John
  5. Instead of the three @ConfigProperty field annotation, inject the GreetingConfiguration instance into the GreetingResource class by using the @Inject annotation, as outlined in the following example. You must also update the message string that the /greeting endpoint returns with the values that you set for the new greeting.content.prize-amount and also the greeting.content.recipients properties that you have added.

    src/main/java/org/acme/config/GreetingResource.java
    import java.util.Optional;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import javax.inject.Inject;
    
    @Path("/greeting")
    public class GreetingResource {
    
        @Inject
        GreetingConfiguration config;
    
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String hello() {
            return config.message() + " " + config.name().orElse("world") + config.suffix() + "\n" + config.content().recipients() + " receive total of candies: " + config.content().prizeAmount();
        }
    }
  6. Compile and start your application in development mode:

    ./mvnw quarkus:dev
    If you do not provide values for the class properties, the application fails to compile and you receive a javax.enterprise.inject.spi.DeploymentException that indicates a missing value. This does not apply to Optional fields and fields with a default value.
  7. To verify that the endpoint returns the message, enter the following command in a new terminal window:

    curl http://localhost:8080/greeting
  8. A message displays containing two lines of output. The first line displays the greeting, and the second line reports the recipients of the prize together with the prize amount, as follows:

    hello quarkus!
    Jane,John receive total of candies: 10
  9. To stop the application, press Ctrl+C.

Classes annotated with @ConfigMapping can be annotated with Bean Validation annotations similar to the following example:

@ConfigMapping(prefix = "greeting")
public class GreetingConfiguration {

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

Your project must include the quarkus-hibernate-validator dependency.

7. Accessing the configuration programmatically

You can define a method in your code to retrieve the values of the configuration properties in your application. By using this mechanism, you can dynamically look up configuration property values or retrieve configuration property values from classes that are either CDI beans or JAX-RS resources.

You can access the configuration by using the org.eclipse.microprofile.config.ConfigProvider.getConfig() method. The getValue method of the config object returns the values of the configuration properties.

Prerequisites
  • You have a Quarkus Maven project.

Procedure
  • Use a method to access the value of a configuration property of any class or object in your application code. Depending on whether or not the value that you want to retrieve is set in a configuration source in your project, you can use one of the following methods:

    • To access the value of a property that is set in a configuration source in your project, for example, in the application.properties file, use the getValue() method:

      String <variable-name> = ConfigProvider.getConfig().getValue("<property-name>", <data-type-class-name>.class);

      For example, to retrieve the value of the greeting.message property that has the data type String, and is assigned to the message variable in your code, use the following syntax:

      String message = config.getValue("greeting.message", String.class);
    • When you want to retrieve a value that is optional or default and might not be defined in your application.properties file or another configuration source in your application, use the getOptionalValue() method:

      String <variable-name> = ConfigProvider.getConfig().getOptionalValue("<property-name>", <data-type-class-name>.class);

      For example, to retrieve the value of the greeting.name property that is optional, has the data type String, and is assigned to the name variable in your code, use the following syntax:

      Optional<String> name = config.getOptionalValue("greeting.name", String.class);

The following snippet shows a variant of the aforementioned GreetingResource class by using the programmatic access to the configuration:

src/main/java/org/acme/config/GreetingResource.java
package org.acme.config;

import java.util.Optional;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@Path("/greeting")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        Config config = ConfigProvider.getConfig();
        String message = config.getValue("greeting.message", String.class);
        String suffix = config.getOptionalValue("greeting.suffix", String.class).orElse("!");
        Optional<String> name = config.getOptionalValue("greeting.name", String.class);


        return message + " " + name.orElse("world") + suffix;
    }
}

8. Property expressions

Property expressions are combinations of property references and plain text strings that you can use to substitute values of properties in your configuration.

Much like a variable, you can use a property expression in Quarkus to substitute a value of a configuration property instead of hardcoding it. A property expression is resolved when java.util.Properties reads the value of the property from a configuration source in your application.

This means that if a configuration property is read from your configuration at compile time, the property expression is also resolved at compile time. If the configuration property is overriden at runtime, its value is resolved at runtime.

You can resolve property expressions by using more than one configuration source. This means that you can use a value of a property that is defined in one configuration source to expand a property expression that you use in another configuration source.

If the value of a property in an expression cannot be resolved, and you do not set a default value for the expression, your application encounters a NoSuchElementException.

8.1. Example usage of property expressions

This section shows examples of how you can use property expressions to achieve greater flexibility when configuring your Quarkus application.

  • Substituting the value of a configuration property:

    To avoid hardcoding property values in your configuration, you can use a property expression. Use the ${<property_name>} syntax to write an expression that references a configuration property, as shown in the following example:

    application.properties
    remote.host=quarkus.io
    callable.url=https://${remote.host}/

    The value of the callable.url property resolves to https://quarkus.io/.

  • Setting a property value that is specific to a particular configuration profile:

    In the following example, the %dev configuration profile and the default configuration profile are set to use data source connection URLs with different host addresses. Depending on the configuration profile with which you start your application, your data source driver uses the database URL that you set for the profile.

    application.properties
    %dev.quarkus.datasource.jdbc.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false
    quarkus.datasource.jdbc.url=jdbc:mysql://remotehost:3306/mydatabase?useSSL=false

    You can achieve the same result in a simplified way by setting a different value for the custom application.server property for each configuration profile. You can then reference the property in the database connection URL of your application, as shown in the following example:

    application.properties
    %dev.application.server=localhost
    application.server=remotehost
    
    quarkus.datasource.jdbc.url=jdbc:mysql://${application.server}:3306/mydatabase?useSSL=false

    The application.server property resolves to the appropriate value depending on the profile that you choose when you run your application.

  • Setting a default value of a property expression:

    You can define a default value for a property expression. Quarkus uses the default value if the value of the property that is required to expand the expression is not resolved from any of your configuration sources. You can set a default value for an expression by using the following syntax:

    ${<property_name>:<default_value>}

    In the following example, the property expression in the data source URL uses mysql.db.server as the default value of the application.server property:

    application.properties
    quarkus.datasource.jdbc.url=jdbc:mysql://${application.server:mysql.db.server}:3306/mydatabase?useSSL=false
  • Nesting property expressions:

    You can compose property expressions by nesting a property expression inside another property expression. When nested property expressions are expanded, the inner expression is expanded first:

    ${<outer_property_name>${<inner_property_name>}}
  • Combining multiple property expressions:

    You can join two or more property expressions together by using the following syntax:

    ${<first_property_name>}${<second_property_name>}
  • Combining property expressions with environment variables:

    You can use property expressions to substitute the values of environment variables. The expression in the following example substitutes the value that is set for the HOST environment variable as the value of the application.host property. When the HOST environment variable is not set, the application.host property uses the value of the remote.host property as the default:

    application.properties
    remote.host=quarkus.io
    application.host=${HOST:${remote.host}}

9. Adding YAML configuration support

Red Hat build of Quarkus supports YAML configuration files through the SmallRye Config implementation of Eclipse MicroProfile Config. You can add the Quarkus Config YAML extension and use the YAML configuration file over the properties file for configuration. Quarkus supports the use of application.yml and application.yaml as the name of the YAML file.

The YAML configuration file takes precedence over the application.properties file. The recommended approach is to delete the application.properties file and use only one type of configuration file to avoid errors.

Procedure
  • Use one of the following methods to add the YAML extension in your project:

    • Open the pom.xml file and add the quarkus-config-yaml extension as a dependency:

      <dependency>
          <groupId>io.quarkus</groupId>
          <artifactId>quarkus-config-yaml</artifactId>
      </dependency>
    • To add the quarkus-config-yaml extension from the command line, enter the following command from your project directory:

      ./mvnw quarkus:add-extension -Dextensions="quarkus-config-yaml"

9.1. Using nested object configuration with YAML

You can define a nested class inside an already existing class. This procedure shows how you can set nested configuration properties for your Quarkus application by using a configuration file in YAML format.

Prerequisites
  • Have a Quarkus Maven project.

  • Have a PostgreSQL data source.

  • Have the following extensions as dependencies in the pom.xml file of your project:

    • quarkus-rest-client

    • quarkus-jdbc-postgresql

    • quarkus-config-yaml

Procedure
  1. Open the src/main/resources/application.yaml configuration file.

  2. Add the nested class configuration properties to your application.yaml file as shown in the following example:

    src/main/resources/application.yaml
    # Properties that configure the JDBC data source driver of your PostgreSQL data source
    quarkus:
      datasource:
        url: jdbc:postgresql://localhost:5432/some-database
        driver: org.postgresql.Driver
        username: quarkus
        password: quarkus
    
    # Property that configures the URL of the endpoint to which the rest client sends requests
    org:
      acme:
        restclient:
          CountriesService/mp-rest/url: https://restcountries.eu/rest
    
    # Property that configures the log message level for your application
    quarkus:
      log:
        category:
    
    # Do not use spaces in names of configuration properties that you place inside quotation marks
          "io.quarkus.category":
            level: INFO

    In a similar way to how you use comments in the application.properties file, you can use comments to describe your configuration properties in YAML format.

    Always use spaces to indent the properties in your YAML configuration file. YAML does not allow you to use tabs for indentation.

9.2. Setting custom configuration profiles with YAML

With Quarkus, you can set configuration properties and values that are specific to different configuration profiles of your application. You can start your application with a specific profile to access a particular configuration. This procedure shows how you can provide a configuration for a specific profile in YAML format.

Prerequisites
  • Have a Quarkus Maven project that is configured to use a PostgreSQL data source with a JDBC data source driver.

  • Have the quarkus-jdbc-postgresql and quarkus-config-yaml extensions as dependencies in the pom.xml file of your project.

Procedure
  1. Open the src/main/resources/application.yaml configuration file.

  2. To set a profile dependent configuration, add the profile name before defining the key-value pairs by using the "%<profile_name>" syntax. Ensure that you place the profile name inside quotation marks.

    In YAML, all strings that begin with a special character must be placed inside quotation marks.

    In the following example, the PostgreSQL database is configured to be available at the jdbc:postgresql://localhost:5432/some-database URL when you start your Quarkus application in development mode:

    src/main/resources/application.yaml
    "%dev":
      # Properties that configure the JDBC data source driver of your PostgreSQL data source
      quarkus:
        datasource:
          url: jdbc:postgresql://localhost:5432/some-database
          driver: org.postgresql.Driver
          username: quarkus
          password: quarkus

9.3. Managing configuration key conflicts

Structured formats such as YAML only support a subset of the possible configuration namespace. The following procedure shows how to resolve a conflict between two configuration properties, quarkus.http.cors and quarkus.http.cors.methods, where one property is the prefix of another.

Prerequisites
  • Have a Quarkus project that is configured to read YAML configuration files.

Procedure
  1. Open your YAML configuration file.

  2. To define a YAML property as a prefix of another property, add a tilde (~) in the scope of the property as shown in the following example:

    quarkus:
      http:
        cors:
          ~: true
          methods: GET,PUT,POST
  3. To compile your Quarkus application in development mode, enter the following command from the project directory:

    ./mvnw quarkus:dev
    You can use YAML keys for conflicting configuration keys at any level because they are not included in the assembly of configuration property name.

10. Using configuration profiles

You can use different configuration profiles depending on your environment. Configuration profiles enable you to have multiple configurations in the same file and to select between them by using a profile name. Red Hat build of Quarkus has three configuration profiles. In addition, you can create your own custom profiles.

Quarkus default profiles:
  • dev: Activated in development mode

  • test: Activated when running tests

  • prod: The default profile when not running in development or test mode

Prerequisites
  • You have a Quarkus Maven project.

Procedure
  1. Open your Java resource file and add the following import statement:

    import io.quarkus.runtime.configuration.ProfileManager;
  2. To display the current configuration profile, add a log invoking the ProfileManager.getActiveProfile() method:

    LOGGER.infof("The application is starting with profile `%s`", ProfileManager.getActiveProfile());
    It is not possible to access the current profile by using the @ConfigProperty("quarkus.profile") method.

10.1. Setting a custom configuration profile

You can create as many configuration profiles as you want. You can have multiple configurations in the same file and you can select between them by using a profile name.

Procedure
  1. To set a custom profile, create a configuration property with the profile name in the application.properties file, where <property_name> is the name of the property, <value> is the property value, and <profile> is the name of a profile:

    %<profile>.<property_name>=<value>

    In the following example configuration, the value of quarkus.http.port is 9090 by default, and becomes 8181 when the dev profile is activated:

    quarkus.http.port=9090
    %dev.quarkus.http.port=8181
  2. Use one of the following methods to enable a profile:

    • Set the quarkus.profile system property.

      • To enable a profile using the quarkus.profile system property, enter the following command:

        mvn -Dquarkus.profile=<value> quarkus:dev
    • Set the QUARKUS_PROFILE environment variable.

      • To enable profile using an environment variable, enter the following command:

        export QUARKUS_PROFILE=<profile>
        The system property value takes precedence over the environment variable value.
  3. To repackage the application and change the profile, enter the following command:

    ./mvnw package -Dquarkus.profile=<profile>
     java -jar target/myapp-runner.jar

    The following example shows a command that activates the prod-aws profile:

    ./mvnw package -Dquarkus.profile=prod-aws
     java -jar target/myapp-runner.jar
The default Quarkus application runtime profile is set to the profile used to build the application. Red Hat build of Quarkus automatically selects a profile depending on your environment mode. For example, when your application is running as a JAR, Quarkus is in prod mode.

11. Setting custom configuration sources

By default, a Quarkus application reads properties from the application.properties file in the src/main/resources subdirectory of your project. Quarkus also allows you to load application configuration properties from other sources according to the MicroProfile Config specification for externalized configuration. You can enable your application to load configuration properties from other sources by defining classes that implement the org.eclipse.microprofile.config.spi.ConfigSource and the org.eclipse.microprofile.config.spi.ConfigSourceProvider interfaces. This procedure demonstrates how you can implement a custom configuration source in your Quarkus project.

Prerequisite
  • Have the Quarkus config-quickstart project.

Procedure
  1. Create a class file in your project that implements the org.eclipse.microprofile.config.spi.ConfigSourceProvider interface. To return a list of ConfigSource objects, you must override its getConfigSources method.

    The following example shows a custom implementation of the ConfigSourceProvider and the ConfigSource interfaces:

    src/main/java/org/acme/config/ExampleConfigSourceProvider.java
    package org.acme.config;
    
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    import org.eclipse.microprofile.config.spi.ConfigSource;
    import org.eclipse.microprofile.config.spi.ConfigSourceProvider;
    
    public class ExampleConfigSourceProvider implements ConfigSourceProvider {
    
        private final int times = 2;
        private final String name = "example";
        private final String value = "value";
    
        @Override
        public Iterable<ConfigSource> getConfigSources(ClassLoader forClassLoader) {
            InMemoryConfigSource configSource = new InMemoryConfigSource(Integer.MIN_VALUE, "example config source");
            for (int i = 0; i < this.times; i++) {
                configSource.add(this.name + ".key" + (i + 1), this.value + (i + 1));
            }
            return Collections.singletonList(configSource);
        }
    
        private static final class InMemoryConfigSource implements ConfigSource {
    
            private final Map<String, String> values = new HashMap<>();
            private final int ordinal;
            private final String name;
    
            private InMemoryConfigSource(int ordinal, String name) {
                this.ordinal = ordinal;
                this.name = name;
            }
    
            public void add(String key, String value) {
                values.put(key, value);
            }
    
            @Override
            public Map<String, String> getProperties() {
                return values;
            }
    
            @Override
            public Set<String> getPropertyNames() {
                return values.keySet();
            }
    
            @Override
            public int getOrdinal() {
                return ordinal;
            }
    
            @Override
            public String getValue(String propertyName) {
                return values.get(propertyName);
            }
    
            @Override
            public String getName() {
                return name;
            }
        }
    }
  2. Create a file named org.eclipse.microprofile.config.spi.ConfigSourceProvider in the src/main/resources/META-INF/services/ subdirectory of your project, and enter the fully qualified name of the class that implements the ConfigSourceProvider in the file that you created:

    src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider
    org.acme.config.ExampleConfigSourceProvider

    You must complete the previous step to ensure that the ConfigSourceProvider that you created is registered and installed when you compile and start your application.

  3. To compile and start your application in development mode, enter the following command:

    ./mvnw quarkus:dev
  4. To verify that the /greeting endpoint returns the expected message, in a terminal window enter the following command:

    curl http://localhost:8080/greeting
  5. When your application successfully reads the custom configuration, you receive the following response:

    hello quarkus!

12. Using custom configuration converters as configuration values

You can store custom types as configuration values by implementing org.eclipse.microprofile.config.spi.Converter<T> and adding its fully qualified class name into the META-INF/services/org.eclipse.microprofile.config.spi.Converter file.

Prerequisites
  • You have created the Quarkus config-quickstart project.

Procedure
  1. Include the fully qualified class name of the converter in your META-INF/services/org.eclipse.microprofile.config.spi.Converter service file as shown in the following example:

    org.acme.config.MicroProfileCustomValueConverter
    org.acme.config.SomeOtherConverter
    org.acme.config.YetAnotherConverter
  2. Implement the converter class to override the convert method:

    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));
        }
    }
    Your custom converter class must be public and must have a public no-argument constructor. Your custom converter class cannot be abstract.
  3. Use your custom type as a configuration value:

    @ConfigProperty(name = "configuration.value.name")
    MicroProfileCustomValue value;

12.1. Setting custom converters priority

The default priority for all Quarkus core converters is 200. For all other converters, the default priority is 100. You can increase the priority of your custom converters by using the javax.annotation.Priority annotation.

The following procedure demonstrates an implementation of a custom converter MicroProfileCustomValue that is assigned a priority of 150, which takes precedence over the MicroProfileCustomValueConverter, whose value is set to 100.

Prerequisites
  • You have created the Quarkus config-quickstart project.

  • You have created a custom configuration converter for your application.

Procedure
  1. Set a priority for your custom converter by annotating the class with the @Priority annotation and passing it a priority value. In the following example, the priority value is set to 150.

    ExampleCustomConverter.java
    package org.acme.config;
    
    import javax.annotation.Priority;
    import org.eclipse.microprofile.config.spi.Converter;
    
    @Priority(150)
    public class ExampleCustomConverter 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);
        }
    }
  2. Create a file named org.eclipse.microprofile.config.spi.Converter in the src/main/resources/META-INF/services/ subdirectory of your project, and enter the fully qualified name of the class that implements the Converter in the file that you created:

    src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter
    org.acme.config.ExampleCustomConverter

    You must complete the previous step to ensure that the Converter that you created is registered and installed when you compile and start your application.

13. Generating an example configuration file for your Quarkus application

You can create an application.properties.example file with all of the available configuration values and documentation for the extensions that your application is configured to use. You can repeat this procedure after you install a new extension to see what additional configuration options were added.

Prerequisites
  • Have a Quarkus Maven project.

Procedure
  • To create an application.properties.example file, enter the following command:

    ./mvnw quarkus:generate-config

    This command creates the application.properties.example file in the src/main/resources/ directory. The file contains all of the configuration options exposed through the extensions that you installed. These options are commented out and have a default value where applicable.

    The following example shows the HTTP port configuration entry from the application.properties.example file:

    #quarkus.http.port=8080
Verification

After you have completed the required configuration, the next step is to compile and then package your Quarkus application. For more information and examples, see the compiling and packaging sections of the Getting started with Quarkus guide.

14. Additional resources