Configuring a Quarkus Application
In this post, we'll go over how to configure a Quarkus application using a specific application.properties file.
Join the DZone community and get the full member experience.
Join For FreeIn 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. 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.
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.
- BookRepository: transactional repository dealing with the EntityManager to persist, retrieve, update, and delete data from a relational database.
- Book: JPA entity representing a book.
- application.properties: property file where we configure the Quarkus application.
- BookResourceTest: Quarkus test class using RESTAssured to test the BookResource.
- 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.
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
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 (e.g. 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
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
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 the 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 the -D
command. 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.
Configuring an application is vital and Quarkus embraces Microprofile Config for that. It 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 do 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.
Published at DZone with permission of Antonio Goncalves, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments