java -Dmyapp.foo.bar=10application.conf"foo" : ${bar}, "foo" : Hello ${who})a.b=c)logdir=${HOME}/logs)Config instances, for thread safety
and easy reasoning about config transformationsThis 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
Config and ConfigObjectTypesafe 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:
Please see NEWS.md in this directory, https://github.com/lightbend/config/blob/main/NEWS.md
.conf file format, read
HOCON.md
in this directoryNOTE: 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.
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.
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");
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:
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.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.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.
There isn't a schema language or anything like that. However, two suggested tools are:
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.
The convenience method ConfigFactory.load() loads the following
(first-listed are higher priority):
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 applicationconfig.file specifies a filesystem path, again
it should include the extension, not be a basenameconfig.url specifies a URLNote: 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.
reference.conf and application.confThe 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.
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.
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:
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:
reference.conf included in your library or
application jar, so there's a default value.$ claude mcp add config \
-- python -m otcore.mcp_server <graph>