Adding Hierarchy to Properties with Typesafe Config

Explains how to use Typesafe Config and HOCON to build hierarchical, layered configuration with clear defaults and overrides. Demonstrates loading multiple config files and reading typed values in Java for more maintainable application settings.

Coveros Staff

August 21, 2015

The Problem

When building any application, library or framework one of the design decisions you make again and again is flexibility. This is shown by many of the choices you make during development. But what about when you want your application, library or framework to be configurable.

What is Typesafe Config?

It is a library that lets you easily load both system and user defined properties. This library includes several features I like but here are three.

One, properties are defined in HOCON a form of relaxed JSON. Here are the full features of this form of JSON but the highlight is that it drops many of the unnecessary quotes and “{”. Making the properties file easier to read and allows you to group properties to associated modules.

Two, it adds easy loading and hierarchy to the properties. This provides an easy way to put default values into a configuration file.

Finally, the library parses the configuration files and converts the value to the matching Java objects ie Boolean, Integer, String, etc. This makes handling of the properties easier.
Example HOCON properties:

first=1
foo {
  value=5
  bar {
    value=10
  }
}

How to load the properties

Now, the documentation explains how they expect you to use it. Each packaged binary includes it’s own application.conf that the system will load. The library then combines the files to one tree object. Additionally, you can load your own properties files and chain them together. Just remember that the order in which you load the properties determines the hierarchy.

Config complexConfig = ConfigFactory.defaultOverrides().
  withFallback(“configFile1.conf”).withFallback(“configFile2.conf”);

This loads the default system values and then the two defined config files which when combined will build the configuration example above.

configFile1.conf

foo {
  value=5
}

configFile2.conf

first=1
foo {
    bar {
      value=10
    }
}

How to handle the properties

After loading the files you now have a Config tree that you can work against. So now you can verify if the object is present and parse it in two easy method calls. The example below showcases this for loading an int. However you can load it as a String, long, boolean, Object and more.

if (complexConfig.hasPath("first")) {
  //Now store the default value from your Config tree
  int defaultValue = complexConfig.getInt("first");
}

What it solves

It allows you to build a tool or system and then hand the configuration to other teams or consumers. This provides a level of abstraction so the user can change the configuration of the library or tool you have built. They can then utilize your project without ever needing to understand the inner workings. Additionally, the hierarchical structure allows you to expand out the configuration to multiple files for easier managing.

Typesafe Config is hosted on GitHub @ https://github.com/typesafehub/config

Coveros Staff

Coveros Staff

This post represents the collective insights of the Coveros team. Our staff consists of software experts who bring deep experience in secure agile development, DevOps, testing, and software quality. Over the past 20 years, Coveros has trained more than 30,000 professionals and worked with half of the Fortune 100 companies on mission-critical software development challenges. We draw on this extensive experience to share practical insights, proven strategies, and real-world solutions that help organizations build better software faster and more securely.