Skip to content
zleonov edited this page Dec 6, 2023 · 22 revisions

Overview

Typesafe Config is one of the more popular configuration libraries for JVM languages. Unfortunately it doesn't offer a convenient way to handle optional properties.

The authors of Typesafe Config take an opinionated view on the handling of default properties:

Many other configuration APIs allow you to provide a default to the getter methods, like this:

    boolean getBoolean(String path, boolean fallback)

Here, if the path has no setting, the fallback would be returned. An API could also return null for unset values, 
so you would check for null:

    // returns null on unset, check for null and fall back
    Boolean getBoolean(String path)

The methods on the Config interface do NOT do this, for two major reasons:

    1. If you use a config setting in two places, the default fallback value gets cut-and-pasted
       and typically out of sync. This can result in Very Evil Bugs.
    2. If the getter returns null (or None, in Scala) then every time you get a setting you have
       to write handling code for null/None and that code will almost always just throw an exception.
       Perhaps more commonly, people forget to check for null at all, so missing settings result
       in NullPointerException.

While this is generally applicable to default values, it does not address scenarios where properties have no defaults and are inherently optional.

For instance, consider a directory copy utility capable of filtering on file extensions. The utility would be expected to transfer all files indiscriminately if no file extensions are specified. Without native capability to handle optional properties, developers would have to resort to writing cumbersome boilerplate code or use a special placeholder value to indicate no filter.

See issues 186, 282, 286, 110, 440 for historical discussion.

Typesafe Config authors do offer some suggestions for dealing with optional properties:


If you want to allow a setting to be missing from `application.conf` in a particular case, then here are some options:

 1. Set it in a `reference.conf` included in your library or application jar, so there's a default value.
 2. Use the `Config.hasPath()` method to check in advance whether the path exists (rather than checking for `null`/`None` after as you might in other APIs).
 3. Catch and handle `ConfigException.Missing`. NOTE: using an exception for control flow like this is much slower than using `Config.hasPath()`; the JVM has to do a lot of work to throw an exception.
 4. In your initialization code, generate a `Config` with your defaults in it (using something like `ConfigFactory.parseMap()`) then fold that default config into your loaded config using `withFallback()`, and use the combined config in your program. "Inlining" your reference config in the code like this is probably less convenient than using a `reference.conf` file, but there may be reasons to do it.
 5. Use `Config.root()` to get the `ConfigObject` for the `Config`; `ConfigObject` implements `java.util.Map` and the `get()` method on `Map` returns null for missing keys. See the API docs for more detail on `Config` vs. `ConfigObject`.
 6. Set the setting to `null` in `reference.conf`, then use `Config.getIsNull` and `Config.hasPathOrNull` to handle `null` in a special way while still throwing an exception if the setting is entirely absent.

However, none of these options provide the functionality to support optional properties as a top-tier feature.

Project specifications

This project is a companion to Typesafe Config, designed to allow users a more convenient and elegant way to handle optional properties.

  • Java 8 or higher is required.

The table below compares and contrasts this class to the Config class from Typesafe Config:

Method Property value Config result Strict mode OptionalConfig result
getXXXX Valid value Returns the property value On/Off Returns the property value
getXXXX Null value Exception Off Returns null
getXXXX Null value Exception On Exception
getXXXX Invalid value Exception On/Off Exception
getXXXX Missing property Exception On/Off Exception
getXXXX Missing value Exception On/Off Exception
getXXXXList Valid list (no null values) Returns the list of values On/Off Returns the list of values
getXXXXList Valid list (contains null values) Exception Off Returns the list of values (including nulls)
getXXXXList Valid list (contains null values) Exception On Exception
getXXXXList Null list Exception Off Returns null
getXXXXList Null list Exception On Exception
getXXXXList Invalid list Exception On/Off Exception
getXXXXList Missing property Exception On/Off Exception
getXXXXList Missing value Exception On/Off Exception
getOptionalXXXX Valid value N/A On/Off Returns an Optional containing the value
getOptionalXXXX Null value N/A On/Off Returns Optional.empty()
getOptionalXXXX Missing property N/A On/Off Returns Optional.empty()
getOptionalXXXX Invalid value N/A On/Off Exception
getOptionalXXXX Missing value N/A On/Off Exception
getOptionalXXXXList Valid list (no null values) N/A On/Off Returns an Optional containing the list of values
getOptionalXXXXList Valid list (contains null values) N/A Off Returns an Optional containing the list of values (including nulls)
getOptionalXXXXList Valid list (contains null values) N/A On Exception
getOptionalXXXXList Null list N/A On/Off Returns Optional.empty()
getOptionalXXXXList Missing property N/A On/Off Returns Optional.empty()
getOptionalXXXXList Invalid list N/A On/Off Exception
getOptionalXXXXList Missing value N/A On/Off Exception

Note that the getEnumList method is re-implemented as getEnumSet by Optional Config.

Additional functionality

Method Functionality
getShort
getOptionalShort
getShortList
getOptionalShortList
Offering methods which operate on properties referencing Short values (for completeness). These methods behave similarly to their Integer and Long counterparts.
getPath
getOptionalPath
getPathList
getOptionalPathList
Offering methods which operate on properties referencing Path values. A valid java.nio.file.Path may refer to an existing file or a directory or may not exist on the filesystem.
getFile
getOptionalFile
getFileList
getOptionalFileList
Offering methods which operate on properties referencing existing files. These methods will throw exceptions if the referenced files do not exist on the filesystem.
getDirectory
getOptionalDirectory
getDirectoryList
getOptionalDirectoryList
Offering methods which operate on properties referencing existing directories. These methods will throw exceptions if the referenced directories do not exist on the filesystem.
at Offering the capability to view nested configuration objects as a standalone OptionalConfig.