MCPcopy
hub / github.com/lightbend/config

github.com/lightbend/config @v1.4.9 sqlite

repository ↗ · DeepWiki ↗ · release v1.4.9 ↗
1,534 symbols 3,856 edges 118 files 255 documented · 17%
README

Configuration library for JVM languages.

Build Status

Overview

  • implemented in plain Java with no dependencies
  • supports files in three formats: Java properties, JSON, and a human-friendly JSON superset
  • merges multiple files across all formats
  • can load from files, URLs, or classpath
  • good support for "nesting" (treat any subtree of the config the same as the whole config)
  • users can override the config with Java system properties, java -Dmyapp.foo.bar=10
  • supports configuring an app, with its framework and libraries, all from a single file such as application.conf
  • parses duration and size settings, "512k" or "10 seconds"
  • converts types, so if you ask for a boolean and the value is the string "yes", or you ask for a float and the value is an int, it will figure it out.
  • JSON superset features:
    • comments
    • includes
    • substitutions ("foo" : ${bar}, "foo" : Hello ${who})
    • properties-like notation (a.b=c)
    • less noisy, more lenient syntax
    • substitute environment variables (logdir=${HOME}/logs)
  • API based on immutable Config instances, for thread safety and easy reasoning about config transformations
  • extensive test coverage

This library limits itself to config files. If you want to load config from a database or something, you would need to write some custom code. The library has nice support for merging configurations so if you build one from a custom source it's easy to merge it in.

Table of Contents generated with DocToc

Essential Information

Binary Releases

Typesafe Config is compatible with Java 8 and above.

You can find published releases on Maven Central.

<dependency>
    <groupId>com.typesafe</groupId>
    <artifactId>config</artifactId>
    <version>1.4.4</version>
</dependency>

sbt dependency:

libraryDependencies += "com.typesafe" % "config" % "1.4.4"

Link for direct download if you don't use a dependency manager:

  • https://repo1.maven.org/maven2/com/typesafe/config/

Release Notes

Please see NEWS.md in this directory, https://github.com/lightbend/config/blob/main/NEWS.md

API docs

  • Online: https://lightbend.github.io/config/latest/api/
  • also published in jar form
  • consider reading this README first for an intro
  • for questions about the .conf file format, read HOCON.md in this directory

Bugs and Patches

NOTE: Please read Readme #Maintained-by before spending time suggesting changes to this library.

Report bugs to the GitHub issue tracker. Send patches as pull requests on GitHub.

Before we can accept pull requests, you will need to agree to the Akka Contributor License Agreement online, using your GitHub account - it takes 30 seconds. You can do this at https://contribute.akka.io/contribute/cla

Please see CONTRIBUTING for more including how to make a release.

Build

The build uses sbt and the tests are written in Scala; however, the library itself is plain Java and the published jar has no Scala dependency.

Using the Library

API Example

import com.typesafe.config.ConfigFactory

Config conf = ConfigFactory.load();
int bar1 = conf.getInt("foo.bar");
Config foo = conf.getConfig("foo");
int bar2 = foo.getInt("bar");

Longer Examples

See the examples in the examples/ directory.

You can run these from the sbt console with the commands project config-simple-app-java and then run.

In brief, as shown in the examples:

  • libraries should use a Config instance provided by the app, if any, and use ConfigFactory.load() if no special Config is provided. Libraries should put their defaults in a reference.conf on the classpath.
  • apps can create a Config however they want (ConfigFactory.load() is easiest and least-surprising), then provide it to their libraries. A Config can be created with the parser methods in ConfigFactory or built up from any file format or data source you like with the methods in ConfigValueFactory.

Immutability

Objects are immutable, so methods on Config which transform the configuration return a new Config. Other types such as ConfigParseOptions, ConfigResolveOptions, ConfigObject, etc. are also immutable. See the API docs for details of course.

Schemas and Validation

There isn't a schema language or anything like that. However, two suggested tools are:

  • use the checkValid() method
  • access your config through a Settings class with a field for each setting, and instantiate it on startup (immediately throwing an exception if any settings are missing)

In Scala, a Settings class might look like:

class Settings(config: Config) {

    // validate vs. reference.conf
    config.checkValid(ConfigFactory.defaultReference(), "simple-lib")

    // non-lazy fields, we want all exceptions at construct time
    val foo = config.getString("simple-lib.foo")
    val bar = config.getInt("simple-lib.bar")
}

See the examples/ directory for a full compilable program using this pattern.

Standard behavior

The convenience method ConfigFactory.load() loads the following (first-listed are higher priority):

  • system properties
  • application.conf (all resources on classpath with this name)
  • application.json (all resources on classpath with this name)
  • application.properties (all resources on classpath with this name)
  • reference.conf (all resources on classpath with this name)

The idea is that libraries and frameworks should ship with a reference.conf in their jar. Applications should provide an application.conf, or if they want to create multiple configurations in a single JVM, they could use ConfigFactory.load("myapp") to load their own myapp.conf.

Libraries and frameworks should default to ConfigFactory.load() if the application does not provide a custom Config object. This way, libraries will see configuration from application.conf and users can configure the whole app, with its libraries, in a single application.conf file.

Libraries and frameworks should also allow the application to provide a custom Config object to be used instead of the default, in case the application needs multiple configurations in one JVM or wants to load extra config files from somewhere. The library examples in examples/ show how to accept a custom config while defaulting to ConfigFactory.load().

For applications using application.{conf,json,properties}, system properties can be used to force a different config source (e.g. from command line -Dconfig.file=path/to/config-file):

  • config.resource specifies a resource name - not a basename, i.e. application.conf not application
  • config.file specifies a filesystem path, again it should include the extension, not be a basename
  • config.url specifies a URL

Note: you need to pass -Dconfig.file=path/to/config-file before the jar itself, e.g. java -Dconfig.file=path/to/config-file.conf -jar path/to/jar-file.jar. Same applies for -Dconfig.resource=config-file.conf

These system properties specify a replacement for application.{conf,json,properties}, not an addition. They only affect apps using the default ConfigFactory.load() configuration. In the replacement config file, you can use include "application" to include the original default config file; after the include statement you could go on to override certain settings.

If you set config.resource, config.file, or config.url on-the-fly from inside your program (for example with System.setProperty()), be aware that ConfigFactory has some internal caches and may not see new values for system properties. Use ConfigFactory.invalidateCaches() to force-reload system properties.

Note about resolving substitutions in reference.conf and application.conf

The substitution syntax ${foo.bar} will be resolved twice. First, all the reference.conf files are merged and then the result gets resolved. Second, all the application.conf are layered over the unresolved reference.conf and the result of that gets resolved again.

The implication of this is that the reference.conf stack has to be self-contained; you can't leave an undefined value ${foo.bar} to be provided by application.conf. It is however possible to override a variable that reference.conf refers to, as long as reference.conf also defines that variable itself.

Merging config trees

Any two Config objects can be merged with an associative operation called withFallback, like merged = firstConfig.withFallback(secondConfig).

The withFallback operation is used inside the library to merge duplicate keys in the same file and to merge multiple files. ConfigFactory.load() uses it to stack system properties over application.conf over reference.conf.

You can also use withFallback to merge in some hardcoded values, or to "lift" a subtree up to the root of the configuration; say you have something like:

foo=42
dev.foo=57
prod.foo=10

Then you could code something like:

Config devConfig = originalConfig
                     .getConfig("dev")
                     .withFallback(originalConfig)

There are lots of ways to use withFallback.

How to handle defaults

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.

For most situations, failure to have a setting is simply a bug to fix (in either code or the deployment environment). Therefore, if a setting is unset, by default the getters on the Config interface throw an exception.

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.hasPat

Extension points exported contracts — how you extend this code

ConfigMergeable (Interface)
Marker for types whose instances can be merged, that is Config and ConfigValue. Instances of {@code Conf [7 implementers]
config/src/main/java/com/typesafe/config/ConfigMergeable.java
ConfigNode (Interface)
A node in the syntax tree for a HOCON or JSON document. Note: at present there is no way to obtain an instance of t [15 …
config/src/main/java/com/typesafe/config/parser/ConfigNode.java
ConfigIncluder (Interface)
Implement this interface and provide an instance to {@link ConfigParseOptions#setIncluder ConfigParseOptions.setIncluder [2 …
config/src/main/java/com/typesafe/config/ConfigIncluder.java
ConfigList (Interface)
Subtype of ConfigValue representing a list value, as in JSON's [1,2,3] syntax. ConfigList i [2 implementers]
config/src/main/java/com/typesafe/config/ConfigList.java
ConfigIncluderClasspath (Interface)
Implement this in addition to ConfigIncluder if you want to support inclusion of files with the {@code [2 implementers]
config/src/main/java/com/typesafe/config/ConfigIncluderClasspath.java

Core symbols most depended-on inside this repo

add
called by 123
config/src/main/java/com/typesafe/config/impl/SimpleConfigList.java
get
called by 120
config/src/main/java/com/typesafe/config/ConfigObject.java
size
called by 78
config/src/main/java/com/typesafe/config/impl/SimpleConfigList.java
origin
called by 71
config/src/main/java/com/typesafe/config/Config.java
length
called by 66
config/src/main/java/com/typesafe/config/impl/Path.java
put
called by 61
config/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
trace
called by 51
config/src/main/java/com/typesafe/config/impl/ConfigImpl.java
isEmpty
called by 47
config/src/main/java/com/typesafe/config/Config.java

Shape

Method 1,346
Class 152
Interface 24
Enum 12

Languages

Java100%

Modules by API surface

config/src/main/java/com/typesafe/config/impl/Tokens.java93 symbols
config/src/main/java/com/typesafe/config/impl/SimpleConfig.java90 symbols
config/src/main/java/com/typesafe/config/impl/Parseable.java85 symbols
config/src/main/java/com/typesafe/config/impl/ConfigImpl.java56 symbols
config/src/main/java/com/typesafe/config/Config.java52 symbols
config/src/main/java/com/typesafe/config/impl/SimpleConfigList.java49 symbols
config/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java45 symbols
config/src/main/java/com/typesafe/config/ConfigException.java44 symbols
config/src/main/java/com/typesafe/config/impl/AbstractConfigValue.java39 symbols
config/src/main/java/com/typesafe/config/impl/Tokenizer.java38 symbols
config/src/main/java/com/typesafe/config/impl/ConfigDelayedMergeObject.java36 symbols
config/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java32 symbols

Datastores touched

(mongodb)Database · 1 repos

For agents

$ claude mcp add config \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact