In this blog post I’ll show you how to configure a Quarkus application using the specific application.properties file as well as the Microprofile Config API (check my other post for configuring with profiles). To break it into more details you will learn:

How to configure a Quarkus application and have separate values for development and test

How to use Microprofile Config to inject values

How to configure logging

How to pass system properties

Use Case

In this example we have one REST Endpoint that uses a repository to persist and retrieve books from a database:

BookResource : a JAX-RS endpoint with a set of methods to GET, POST, UPDATE and DELETE a book using the BookRepository

: a JAX-RS endpoint with a set of methods to GET, POST, UPDATE and DELETE a book using the BookRepository : transactional repository dealing with the EntityManager to persist, retrieve, update and delete data from a relational database

: transactional repository dealing with the EntityManager to persist, retrieve, update and delete data from a relational database Book : JPA entity representing a book

: JPA entity representing a book application.properties : property file where we configure the Quarkus application

: property file where we configure the Quarkus application BookResourceTest : Quarkus test class using RESTAssured to test the BookResource

: Quarkus test class using RESTAssured to test the Postgres is used in development and H2 is used in test

This is a simple application in terms of business logic. The idea of this blog post is to show you how Quarkus can configure this application depending on the environment (dev vs test) or by injecting external values.

Configuring the Application

By default, Quarkus reads the configuration of an application by reading the application.properties file located under the src/main/resources directory. In fact, most of the properties of your application can fit in this file. If you have legacy code with a META-INF/persistence.xml or beans.xml , Quarkus will detect these files and use their configuration. But you can also get rid of the XML deployment descriptors and only use the application.properties file (which is recommended by Quarkus).

Coming back to our use case, we need to tell Quarkus to use a Postgres database for our development environment. For that, Quarkus has a set of already defined properties that you just need to set in the application.properties file:

quarkus.datasource.url = jdbc:postgresql://localhost:5432/cdbookstoreDB quarkus.datasource.driver = org.postgresql.Driver quarkus.datasource.username = cdbookstoreDB quarkus.datasource.password = h2g2

In our test environment we want to use an H2 database. To have a different database you create a new application.properties file under src/test/resources and override the needed properties (here the H2 driver and URL). Quarkus will use the appropriate application.properties depending if we are in dev or test:

quarkus.datasource.url = jdbc:h2:mem:cdbookstoreDB quarkus.datasource.driver = org.h2.Driver

Injecting a Configuration Value

Often we need to configure bits and pieces of our application depending on the environment as we just saw (test, dev, prod…) but also depending on the deployment (eg. a business rule that changes depending on the country). For that, Quarkus uses MicroProfile Config to inject the configuration in the application. The injection uses the @ConfigProperty annotation (you don’t even need to write @Inject @ConfigProperty ). Below, we inject a value for the ISBN prefix that we use when persisting a book:

@ApplicationScoped @Path("books") public class BookResource { @ConfigProperty(name = "isbn.prefix") String isbnPrefix; @POST @Consumes(MediaType.APPLICATION_JSON) @Transactional(REQUIRED) public Response create(Book book, @Context UriInfo uriInfo) { String isbn = isbnPrefix + "-" + (int) (Math.random() * 1000); book.setIsbn(isbn); final Book created = bookRepository.create(book); URI createdURI = uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getId())).build(); return Response.created(createdURI).build(); }

The value of the ISBN prefix is defined in the application.properties :

isbn.prefix=DEV

And of course the value can be overridden in the test environment (and also passing system properties as you’ll see below):

isbn.prefix=TEST

Configuring Logging

The other use case that we all face is configuring logs. There is an entire guide on Quarkus about configuring logs. Quarkus supports several logging APIs: JUL ( java.util.logging ), JBoss Logging, SLF4J and Apache Commons Logging. In the code below I am using the SLF4J logger:

package org.agoncal.sample.quarkus.book.rest; @ApplicationScoped @Path("books") public class BookResource { private final Logger log = LoggerFactory.getLogger(BookResource.class); @GET @Produces(MediaType.APPLICATION_JSON) public Response findAll() { log.debug("Getting all the books"); return ok(bookRepository.findAll()).build(); }

Because the BookResource is under the org.agoncal package, if I want to turn the logging to INFO in development, it’s just a matter of setting the right value in the application.properties :

quarkus.log.category."org.agoncal".level=INFO

And as you might have guessed by now, you can use a different logging level in the test environment just by overriding its value:

quarkus.log.category."org.agoncal".level=DEBUG

Configuring with System Properties

The Microprofile Config also allows you to configure the application by passing system properties (and also environment variables). You can do so when running on HotSpot (by passing variables to the JVM such as java -Disbn.prefix=PROD ) or pass properties to the executable binary. Let’s do that.

One of the beauties of Quarkus is that it can be used to build native code thanks to Graal VM. To do so, you need to have setup Graal VM, set the GRAALVM_HOME variable. Then, leave Maven and the Quarkus plugin do the rest just by executing a mvn clean package -Pnative command. You end up with a binary file in the target folder (in the case of this sample, the file is 52Mb and is called configuration-1.0-runner ). You can then execute the binary passing properties with a -D . As you can see below, we override the isbn.prefix property:

$ ./configuration-1.0-runner $ ./configuration-1.0-runner -Disbn.prefix=PROD $ ./configuration-1.0-runner -Disbn.prefix=PROD -Dquarkus.log.category.\"org.agoncal\".level=DEBUG

When configuring the logs, make sure you escape the log category (here org.agoncal ) when passing it as a system property.

Conclusion

Configuring an application is vital and Quarkus embraces Microprofile Config for that. If goes even further by centralizing all the configuration into a single file ( application.properties ) instead of spreading the configuration throughout several deployment descriptors ( persistence.xml , web.xml , beans.xml …). Configuration is a rich topic that is covered by the Microprofile Config. You can configuration depending on profiles, you can write your custom configuration sources, converters and even prioritize these converters.

Download the code, give it a try and leave some comments.

References