configuration library for JVM languages using HOCON files

Overview

Configuration library for JVM languages.

Maven Central Build Status

If you have questions or are working on a pull request or just curious, please feel welcome to join the chat room: Join chat https://gitter.im/lightbend/config

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

Version 1.2.1 and earlier were built for Java 6, while newer versions (1.3.0 and above) will be built for Java 8.

You can find published releases on Maven Central.

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

sbt dependency:

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

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

Release Notes

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

API docs

Bugs and Patches

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 Typesafe Contributor License Agreement online, using your GitHub account - it takes 30 seconds. You can do this at https://www.lightbend.com/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

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.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<String,?> 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.

The recommended path (for most cases, in most apps) is that you require all settings to be present in either reference.conf or application.conf and allow ConfigException.Missing to be thrown if they are not. That's the design intent of the Config API design.

Consider the "Settings class" pattern with checkValid() to verify that you have all settings when you initialize the app. See the Schemas and Validation section of this README for more details on this pattern.

If you do need a setting to be optional: checking hasPath() in advance should be the same amount of code (in Java) as checking for null afterward, without the risk of NullPointerException when you forget. In Scala, you could write an enrichment class like this to use the idiomatic Option syntax:

implicit class RichConfig(val underlying: Config) extends AnyVal {
  def getOptionalBoolean(path: String): Option[Boolean] = if (underlying.hasPath(path)) {
     Some(underlying.getBoolean(path))
  } else {
     None
  }
}

Since this library is a Java library it doesn't come with that out of the box, of course.

It is understood that sometimes defaults in code make sense. For example, if your configuration lets users invent new sections, you may not have all paths up front and may be unable to set up defaults in reference.conf for dynamic paths. The design intent of Config isn't to prohibit inline defaults, but simply to recognize that it seems to be the 10% case (rather than the 90% case). Even in cases where dynamic defaults are needed, you may find that using withFallback() to build a complete nothing-missing Config in one central place in your code keeps things tidy.

Whatever you do, please remember not to cut-and-paste default values into multiple places in your code. You have been warned! :-)

Understanding Config and ConfigObject

To read and modify configuration, you'll use the Config interface. A Config looks at a JSON-equivalent data structure as a one-level map from paths to values. So if your JSON looks like this:

  "foo" : {
    "bar" : 42
    "baz" : 43
  }

Using the Config interface, you could write conf.getInt("foo.bar"). The foo.bar string is called a path expression (HOCON.md has the syntax details for these expressions). Iterating over this Config, you would get two entries; "foo.bar" : 42 and "foo.baz" : 43. When iterating a Config you will not find nested Config (because everything gets flattened into one level).

When looking at a JSON tree as a Config, null values are treated as if they were missing. Iterating over a Config will skip null values.

You can also look at a Config in the way most JSON APIs would, through the ConfigObject interface. This interface represents an object node in the JSON tree. ConfigObject instances come in multi-level trees, and the keys do not have any syntax (they are just strings, not path expressions). Iterating over the above example as a ConfigObject, you would get one entry "foo" : { "bar" : 42, "baz" : 43 }, where the value at "foo" is another nested ConfigObject.

In ConfigObject, null values are visible (distinct from missing values), just as they are in JSON.

ConfigObject is a subtype of ConfigValue, where the other subtypes are the other JSON types (list, string, number, boolean, null).

Config and ConfigObject are two ways to look at the same internal data structure, and you can convert between them for free using Config.root() and ConfigObject.toConfig().

ConfigBeanFactory

As of version 1.3.0, if you have a Java object that follows JavaBean conventions (zero-args constructor, getters and setters), you can automatically initialize it from a Config.

Use ConfigBeanFactory.create(config.getConfig("subtree-that-matches-bean"), MyBean.class) to do this.

Creating a bean from a Config automatically validates that the config matches the bean's implied schema. Bean fields can be primitive types, typed lists such as List<Integer>, java.time.Duration, ConfigMemorySize, or even a raw Config, ConfigObject, or ConfigValue (if you'd like to deal with a particular value manually).

Using HOCON, the JSON Superset

The JSON superset is called "Human-Optimized Config Object Notation" or HOCON, and files use the suffix .conf. See HOCON.md in this directory for more detail.

After processing a .conf file, the result is always just a JSON tree that you could have written (less conveniently) in JSON.

Features of HOCON

  • Comments, with # or //
  • Allow omitting the {} around a root object
  • Allow = as a synonym for :
  • Allow omitting the = or : before a { so foo { a : 42 }
  • Allow omitting commas as long as there's a newline
  • Allow trailing commas after last element in objects and arrays
  • Allow unquoted strings for keys and values
  • Unquoted keys can use dot-notation for nested objects, foo.bar=42 means foo { bar : 42 }
  • Duplicate keys are allowed; later values override earlier, except for object-valued keys where the two objects are merged recursively
  • include feature merges root object in another file into current object, so foo { include "bar.json" } merges keys in bar.json into the object foo
  • include with no file extension includes any of .conf, .json, .properties
  • you can include files, URLs, or classpath resources; use include url("http://example.com") or file() or classpath() syntax to force the type, or use just include "whatever" to have the library do what you probably mean (Note: url()/file()/classpath() syntax is not supported in Play/Akka 2.0, only in later releases.)
  • substitutions foo : ${a.b} sets key foo to the same value as the b field in the a object
  • substitutions concatenate into unquoted strings, foo : the quick ${colors.fox} jumped
  • substitutions fall back to environment variables if they don't resolve in the config itself, so ${HOME} would work as you expect. Also, most configs have system properties merged in so you could use ${user.home}.
  • substitutions normally cause an error if unresolved, but there is a syntax ${?a.b} to permit them to be missing.
  • += syntax to append elements to arrays, path += "/bin"
  • multi-line strings with triple quotes as in Python or Scala

Examples of HOCON

All of these are valid HOCON.

Start with valid JSON:

{
    "foo" : {
        "bar" : 10,
        "baz" : 12
    }
}

Drop root braces:

"foo" : {
    "bar" : 10,
    "baz" : 12
}

Drop quotes:

foo : {
    bar : 10,
    baz : 12
}

Use = and omit it before {:

foo {
    bar = 10,
    baz = 12
}

Remove commas:

foo {
    bar = 10
    baz = 12
}

Use dotted notation for unquoted keys:

foo.bar=10
foo.baz=12

Put the dotted-notation fields on a single line:

foo.bar=10, foo.baz=12

The syntax is well-defined (including handling of whitespace and escaping). But it handles many reasonable ways you might want to format the file.

Note that while you can write HOCON that looks a lot like a Java properties file (and many properties files will parse as HOCON), the details of escaping, whitespace handling, comments, and so forth are more like JSON. The spec (see HOCON.md in this directory) has some more detailed notes on this topic.

Uses of Substitutions

The ${foo.bar} substitution feature lets you avoid cut-and-paste in some nice ways.

Factor out common values

This is the obvious use,

standard-timeout = 10ms
foo.timeout = ${standard-timeout}
bar.timeout = ${standard-timeout}

Inheritance

If you duplicate a field with an object value, then the objects are merged with last-one-wins. So:

foo = { a : 42, c : 5 }
foo = { b : 43, c : 6 }

means the same as:

foo = { a : 42, b : 43, c : 6 }

You can take advantage of this for "inheritance":

data-center-generic = { cluster-size = 6 }
data-center-east = ${data-center-generic}
data-center-east = { name = "east" }
data-center-west = ${data-center-generic}
data-center-west = { name = "west", cluster-size = 8 }

Using include statements you could split this across multiple files, too.

If you put two objects next to each other (close brace of the first on the same line with open brace of the second), they are merged, so a shorter way to write the above "inheritance" example would be:

data-center-generic = { cluster-size = 6 }
data-center-east = ${data-center-generic} { name = "east" }
data-center-west = ${data-center-generic} { name = "west", cluster-size = 8 }

Optional system or env variable overrides

In default uses of the library, exact-match system properties already override the corresponding config properties. However, you can add your own overrides, or allow environment variables to override, using the ${?foo} substitution syntax.

basedir = "/whatever/whatever"
basedir = ${?FORCED_BASEDIR}

Here, the override field basedir = ${?FORCED_BASEDIR} simply vanishes if there's no value for FORCED_BASEDIR, but if you set an environment variable FORCED_BASEDIR for example, it would be used.

A natural extension of this idea is to support several different environment variable names or system property names, if you aren't sure which one will exist in the target environment.

Object fields and array elements with a ${?foo} substitution value just disappear if the substitution is not found:

// this array could have one or two elements
path = [ "a", ${?OPTIONAL_A} ]

By setting the JVM property -Dconfig.override_with_env_vars=true it is possible to override any configuration value using environment variables even if an explicit substitution is not specified.

The environment variable value will override any pre-existing value and also any value provided as Java property.

With this option enabled only environment variables starting with CONFIG_FORCE_ are considered, and the name is mangled as follows:

  • the prefix CONFIG_FORCE_ is stripped
  • single underscore(_) is converted into a dot(.)
  • double underscore(__) is converted into a dash(-)
  • triple underscore(___) is converted into a single underscore(_)

i.e. The environment variable CONFIG_FORCE_a_b__c___d set the configuration key a.b-c_d

Set array values outside configuration files

Setting the value of array items from java properties or environment variables require specifying the index in the array for the value. So, while in HOCON you can set multiple values into an array or append to an array:

## HOCON
items = ["a", "b"]
items += "c"

Using java properties you specify the exact position:

-Ditems.0="a" -Ditems.1="b"

as well as with environment variables:

export CONFIG_FORCE_items_0=a
export CONFIG_FORCE_items_1=b

Concatenation

Values on the same line are concatenated (for strings and arrays) or merged (for objects).

This is why unquoted strings work, here the number 42 and the string foo are concatenated into a string 42 foo:

key : 42 foo

When concatenating values into a string, leading and trailing whitespace is stripped but whitespace between values is kept.

Quoted or unquoted strings can also concatenate with substitutions of course:

tasks-url : ${base-url}/tasks
tasks-url : ${base-url}"tasks:colon-must-be-quoted"

Note: the ${} syntax must be outside the quotes!

A concatenation can refer to earlier values of the same field:

path : "/bin"
path : ${path}":/usr/bin"

Arrays can be concatenated as well:

path : [ "/bin" ]
path : ${path} [ "/usr/bin" ]

There is a shorthand for appending to arrays:

// equivalent to: path = ${?path} [ "/usr/bin" ]
path += "/usr/bin"

To prepend or insert into an array, there is no shorthand.

When objects are "concatenated," they are merged, so object concatenation is just a shorthand for defining the same object twice. The long way (mentioned earlier) is:

data-center-generic = { cluster-size = 6 }
data-center-east = ${data-center-generic}
data-center-east = { name = "east" }

The concatenation-style shortcut is:

data-center-generic = { cluster-size = 6 }
data-center-east = ${data-center-generic} { name = "east" }

When concatenating objects and arrays, newlines are allowed inside each object or array, but not between them.

Non-newline whitespace is never a field or element separator. So [ 1 2 3 4 ] is an array with one unquoted string element "1 2 3 4". To get an array of four numbers you need either commas or newlines separating the numbers.

See the spec for full details on concatenation.

Note: Play/Akka 2.0 have an earlier version that supports string concatenation, but not object/array concatenation. += does not work in Play/Akka 2.0 either. Post-2.0 versions support these features.

Miscellaneous Notes

Debugging Your Configuration

If you have trouble with your configuration, some useful tips.

  • Set the Java system property -Dconfig.trace=loads to get output on stderr describing each file that is loaded. Note: this feature is not included in the older version in Play/Akka 2.0.
  • Use myConfig.root().render() to get a Config as a string with comments showing where each value came from. This string can be printed out on console or logged to a file etc.
  • If you see errors like com.typesafe.config.ConfigException$Missing: No configuration setting found for key foo, and you're sure that key is defined in your config file, they might appear e.g. when you're loading configuration from a thread that's not the JVM's main thread. Try passing the ClassLoader in manually - e.g. with ConfigFactory.load(getClass().getClassLoader()) or setting the context class loader. If you don't pass one, Lightbend Config uses the calling thread's contextClassLoader, and in some cases, it may not have your configuration files in its classpath, so loading the config on that thread can yield unexpected, erroneous results.

Supports Java 8 and Later

Currently the library is maintained against Java 8, but version 1.2.1 and earlier will work with Java 6.

Please use 1.2.1 if you need Java 6 support, though some people have expressed interest in a branch off of 1.3.x supporting Java 7. If you want to work on that branch you might bring it up on chat. We can release a jar for Java 7 if someone(s) steps up to maintain the branch. The master branch does not use Java 8 "gratuitously" but some APIs that use Java 8 types will need to be removed.

Rationale for Supported File Formats

(For the curious.)

The three file formats each have advantages.

  • Java .properties:
    • Java standard, built in to JVM
    • Supported by many tools such as IDEs
  • JSON:
    • easy to generate programmatically
    • well-defined and standard
    • bad for human maintenance, with no way to write comments, and no mechanisms to avoid duplication of similar config sections
  • HOCON/.conf:
    • nice for humans to read, type, and maintain, with more lenient syntax
    • built-in tools to avoid cut-and-paste
    • ways to refer to the system environment, such as system properties and environment variables

The idea would be to use JSON if you're writing a script to spit out config, and use HOCON if you're maintaining config by hand. If you're doing both, then mix the two.

Two alternatives to HOCON syntax could be:

  • YAML is also a JSON superset and has a mechanism for adding custom types, so the include statements in HOCON could become a custom type tag like !include, and substitutions in HOCON could become a custom tag such as !subst, for example. The result is somewhat clunky to write, but would have the same in-memory representation as the HOCON approach.
  • Put a syntax inside JSON strings, so you might write something like "$include" : "filename" or allow "foo" : "${bar}". This is a way to tunnel new syntax through a JSON parser, but other than the implementation benefit (using a standard JSON parser), it doesn't really work. It's a bad syntax for human maintenance, and it's not valid JSON anymore because properly interpreting it requires treating some valid JSON strings as something other than plain strings. A better approach is to allow mixing true JSON files into the config but also support a nicer format.

Other APIs (Wrappers, Ports and Utilities)

This may not be comprehensive - if you'd like to add mention of your wrapper, just send a pull request for this README. We would love to know what you're doing with this library or with the HOCON format.

Guice integration

Java (yep!) wrappers for the Java library

Scala wrappers for the Java library

Clojure wrappers for the Java library

Kotlin wrappers for the Java library

Scala port

Ruby port

Puppet module

Python port

C++ port

JavaScript port

C# port

Rust port

Go port

Linting tool

Online playground

Maintenance notes

License

The license is Apache 2.0, see LICENSE-2.0.txt.

Maintained by

This project is maintained mostly by @havocp and @akka-team.

Feel free to ping above maintainers for code review or discussions. Pull requests are very welcome–thanks in advance!

Comments
  • Add ConfigDocument API

    Add ConfigDocument API

    This work came out of the discussion in https://github.com/typesafehub/config/issues/272.

    ~~These commits add a new grouping of classes, ConfigNode, to the library, which are used to form an AST. This AST contains all the tokens from which it was parsed, so the original text can be reproduced from them.~~

    ~~I'm opening this up for review now as the implementation is complete, so I think that portion is ready for review. The testing code is rough right now, largely because of the difficulty involved with crafting instances of ConfigNodeComplexValue by hand, so I'm still working on improving that, although any feedback on that front is welcome.~~

    This PR adds the ConfigDocument API in its entirety, including its backend representation with ConfigNodes, the ConfigDocument Parser, and the ConfigDocument Interface.

    opened by MSLilah 43
  • Proposal to convert the main codebase to Scala

    Proposal to convert the main codebase to Scala

    Proposal to convert the main codebase to Scala

    Purpose

    The initial idea was that lightbend/config is a dependency of scalafmt so if we change the API to Scala we could cross compile the library to Scala Native and then scalafmt could be compiled to Scala Native as well.

    Process

    The port was started with Config as that is the core interface in the library and given Config is an interface it could easily be converted to a trait and the process could move on. But true to form this interface has a Java varargs argument so this was a difficult start nonetheless. The port was done file by file until complete with the exception of the Java Optional annotation. Some process points are as follows:

    • The bulk of the conversion was done by IntelliJ’s converter from Java to Scala.
    • Modified the code as little as possible to compile and pass tests
    • Used import aliases for java.util as ju and java.lang as jl to highlight the code for better readability
    • Only moved inner classes/objects in one case where using from Java was not possible.
    • Commented all break and continue statements to make them easier to follow.
    • Made small changes to immutable here and there
    • Used scala.collection.JavaConverters for explicit conversions
    • Left/changed Scala methods without parameters without parentheses as this is more idiomatic for Scala
    • Did not change tests except for removing parens and using type ascriptions since Scala type safety is more robust

    Deficiencies

    • The biggest issue is that creating Java enums in Scala is at best half baked. They work fine in Scala but are verbose and maintain the API faithfully but are not as useful in Java. Individually they can be used by adding the parentheses but cannot participate in switch statements without reverting to name() or ordinal() so if statements would be the best approach. They also are not marked as enums in byte code so they can not be used in and EnumMap but the implementation used a TreeMap which worked fine to preserve order.

    • The API has been maintained faithfully but the code will not be source compatible for either Java or Scala mostly do the parens in Scala and the enums in Java. The changes to adopt would be very easy to do however.

    • The Optional annotation and reflection based code would need to be evaluated in order to make something appropriate for Scala Native and Scala.JS. There is portable-scala-reflect but that would introduce a dependency and the library has none. Also, Scala Native does not support this reflection API yet.

    • Some access modifiers have been altered from the conversion. Some have been restored as they were commented out but some were left public in order to make the Java code using the Scala compile. The sheer bulk of code changed made perfection very difficult. Auditing the code could reintroduce tighter control where needed in the implementation code where the permissions were changed.

    Conclusions and path forward

    Certainly this was a significant amount of work so it should be in the community’s best interest to find a path forward if possible. One potential is to use this code as a path forward for Scala 2.11+ and above and only maintain bug fixes for the current version for current users of 2.10 through 2.12. This would allow a more flexible upgrade to newer versions for those customers on 2.11+ already.

    One large benefit is that future developers can now code in Scala which is perhaps one of the biggest points for the maintainers.

    Hopefully we can find a useful conclusion to this work that is completed to date.

    opened by ekrich 31
  • Preserve comments across newlines?

    Preserve comments across newlines?

    Hi,

    I've been hacking a bit on porting this library to Ruby ( https://github.com/cprice404/ruby-typesafe-config/blob/master/README.md ). One of the features I'm interested in is the ability to load a config file, modify the data programatically, and write the file back out to disk. It's fine if the formatting changes a bit during the round trip, but retaining as many comments as possible is a huge win and a big part of why I am a fan of the Java library.

    However, I'm a bit confused as to the expected behavior for comments that are separated by a newline. Here's an example config file:

    # These are some opening comments
    
    # These are some additional opening comments
    foo.bar {
      baz = 42
    }
    

    Now, if I load this via ConfigFactory.parseFile, and then render it back to a string (with render options +formatted, +comments, -json, -origincomments), I get this:

    foo {
        # These are some additional opening comments
        bar {
            baz=42
        }
    }
    

    I understand why the comment got moved from the top of the file and is instead attached directly to "bar", but, I was a bit surprised that the very first comment line that had been at the beginning of the file just disappeared entirely. Reading some of the comments in the source code, it sounded like there was some expectation that these comments would be grouped together despite the newline and would all be attached to "bar".

    Is the current behavior expected? Would it be possible to make it save comments across newlines?

    Failing that, might it be worth considering any comments that appear at the very beginning of the file (followed by a blank line) to be "header" comments that would always be rendered at the top of the output during a render operation?

    feature request need help / info / volunteers welcome 
    opened by cprice404 31
  • implement `include required(

    implement `include required("foo")` which throws an error if foo is missing

    I have the following setup

    internal.conf with

    include file("external.conf")
    some.prop = ${foo.bar}
    

    external.conf with

    foo.bar = x 
    

    If external.conf is not to be found, instead of getting a helpful message such as "file not found - external.conf" I get a

     com.typesafe.config.ConfigException$UnresolvedSubstitution: internal.conf: 2: 
        Could not resolve substitution to a value: ${foo.bar}
    

    I think it should at least be configurable so that missing files will throw an exception before trying to resolve substitutions

    feature request faq pretty easy and uncontroversial 
    opened by eranation 30
  • Performance issues during resolve() of large config file

    Performance issues during resolve() of large config file

    A change in substitution handling code (c8f42ef92dd419f99c8eaebdc94f24c8feb1c4db) released as part of 1.3.0 can lead to long running time for Config.resolve(). Performance issues with this commit are already indicated in the commit message and the comment in class ResolveMemos.

    The following code requires more than 3 minutes on a fast machine:

    val config = ConfigFactory.parseFile(file).resolve();
    

    Where file is this config file which in turn includes this config.

    Profiling indicates a hot spot in ResolveMemos.put() where a copy of a HashMap is created.

    Although I am a big fan of the library, I won't be able to create a fix/PR because I don't know the implementation that well. I appreciate any hint for a workaround (changes in the config file).

    candidate for next release need help / info / volunteers welcome 
    opened by MaxLillack 25
  • Add a config.strategy to enable overwrite of properties from env vars

    Add a config.strategy to enable overwrite of properties from env vars

    This PR propose to introduce an alternative config.strategy to enable the overwrite of configurations entries with environment variables even if a substitution is not explicitly provided in the configuration files.

    Rationale:

    We want to be able to dynamically override potentially any configuration option with environment variables. The current env variable substitution mechanism is verbose and have to be explicitly defined for every configuration ahead of time. more on the topic is detailed here: https://github.com/codacy/env2props#rationale

    Unfortunately the approach taken in env2props has a big drawback, getting the bash string substitution correct is not trivial and is error-prone.

    Here I'm proposing to have an alternative implementation of the config.strategy that allow to obtain the very same behavior.

    Notes:

    the mangling of env vars is needed because in a default bash environment:

    $ export A.B=1
    bash: export: `A.B=1': not a valid identifier
    $ export A-B=1
    bash: export: `A-B=1': not a valid identifier
    
    opened by andreaTP 23
  • Impossible to override reference.conf

    Impossible to override reference.conf

    Because reference.conf is fully resolved before merging with main config, the following doesn't work:

    reference.conf:

    myapp {
        storageDir = "."
    }
    myappinternal {
        file1 = ${myapp.storageDir}/file1
        file2 = ${myapp.storageDir}/file2
    }
    

    aplication.conf:

    myapp {
        storageDir = "mydir"
    }
    

    file1 and file2 will not be "mydir/file1" paths but "./file1" instead.

    opened by mikea 22
  • Added support for YAML files.

    Added support for YAML files.

    This pull request adds support for parsing YAML files using the SnakeYAML code. It needs to be tested. I am not 100% sure that it works I do not completely understand the typesafe/config design.

    The reason for this modification is to make it easier to introduce HOCON into environments that use YAML. With this change, a HOCON file can include a YAML file. At least that is the intent! :)

    feature request need help / info / volunteers welcome unclear next steps needs thinking 
    opened by derrickburns 18
  • Repo was moved to lightbend/... github

    Repo was moved to lightbend/... github

    Hi @havocp, Wanted to let you know we're cleaning up repositories and moved this one and other actively maintained repos from typesafehub/ to lightbend/ all things should work fine, and if people go to https://github.com/typesafehub/config they'll be redirected nicely.

    I hope the move is fine with you! I've given you full admin rights of course. We're not intending to change naming or anything in the library, it's perfectly fine with how it is - just wanted to move actual active projects onto the actual active github account rather than the archive/dumping-ground that typesafehub has become over the years.

    faq 
    opened by ktoso 17
  • BeanFactory support with autoconversion

    BeanFactory support with autoconversion

    Hello.

    Improved support for BeanConfig mentioned in pull request #107 (https://github.com/typesafehub/config/pull/107)

    Added support for automatic type conversions plus some tests for those features.

    Ready for questions and comments.

    opened by zstd 16
  • The github project description / website seems inappropriate

    The github project description / website seems inappropriate

    The description reads: Configuration library for JVM languages

    The website is: http://typesafe.com

    I don't think anyone who would like to learn more about this specific project would find the cited website terribly insightful. Perhaps leave that field blank?

    opened by mslinn 15
  • Find a StackOverflowError in config

    Find a StackOverflowError in config

    poc as follow:

      public static void main(String[] args) throws IOException {
    
    
            Config conf = ConfigFactory.parseString("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[");
           
    
        }
    

    and the result:

    image
    opened by BIngDiAn-cn 1
  • Find a StackOverflowError in config

    Find a StackOverflowError in config

    poc as follow:

      public static void main(String[] args)  {
            
            Config conf = ConfigFactory.parseString("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a=1");
            
        }
    

    and the result: image

    opened by BIngDiAn-cn 0
  • Find a StackOverflowError in config

    Find a StackOverflowError in config

    poc as follow:

     public static void main(String[] args) throws IOException {
    
    
            Config conf = ConfigFactory.parseString("{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:{1:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}");
        }
    

    an the result: image

    opened by BIngDiAn-cn 0
  • Add ConfigFloat class to wrap java.lang.Float.

    Add ConfigFloat class to wrap java.lang.Float.

    Instances of java.lang.Float were previously wrapped using ConfigDouble. This had the unfortunate side effect of adding junk values when converting to double. For example float value 1.64e-7f would be rendered as 1.6399999935856613E-7.

    This issue was discovered when testing the HOCON module of the Kotlin Serialization library.

    opened by daniel-jasinski 0
  • Allow passing HOCON string via system property

    Allow passing HOCON string via system property

    References #380

    Hello! This PR provides implementation of feature proposed by @havocp in thread #382

    The goal is to have the ability to pass HOCON content as a string via system property config.config_content. Example: -Dconfig.config_content="param1=Hello\nparam2=world!".

    This helps with some corner-case substitution scenarios, like passing empty list values via system props.

    opened by aerondt 1
  • Is this project active?

    Is this project active?

    I've been using HOCON for all my Scala projects and I'm one happy customer! However, there has been no major feature development while issues and pull requests keep piling up, some of which my team could benefit from such as support for more file types, transformations, and validation. That's why I wanted to know whether there's a roadmap for this project and what all features can we expect in the coming months and years.

    If there's no plan to add any more features in the next couple of years then can anyone suggest any other configuration file format that has at least as many features as HOCON? Would that be Jsonnet?

    opened by vishalovercome 3
KickAss Configuration. An annotation-based configuration system for Java and Kotlin

KAConf 2016-2020 Mario Macías KickAss Configuration v0.9.0 is an Annotation-based configuration system inspired in the wonderful Spring Boot. Its stro

Mario Macías 53 Nov 21, 2022
Modern configuration library for distributed apps written in Java.

Overview cfg4j ("configuration for Java") is a configuration library for Java distributed apps (and more). Features: Open source Easy to use Auto-relo

cfg4j 544 Nov 23, 2022
A simple configuration library for Java applications providing a node structure, a variety of formats, and tools for transformation

Configurate Configurate is a simple configuration library for Java applications that provides a node-based representation of data, able to handle a wi

SpongePowered 274 Jan 3, 2023
A twelve-factor configuration (12factor.net/config) library for Java 8+

dotenv A twelve-factor configuration library for Java 8+. Features: seamless integration with Guice (prefer Spring? see here); zero dependencies; avai

Stanley Shyiko 42 Oct 1, 2022
Library for configuration management API

Archaius Features Archaius includes a set of configuration management APIs used by Netflix. It provides the following functionality: Dynamic, Typed Pr

Netflix, Inc. 2.4k Dec 22, 2022
A gradle plugin generates resConfig & languages array from project res folder.

For Android application projects that accept user-submitted translations, the number of supported languages may be large and growing. When new languages are added, developers need to manually update resConfig (1) and language array xml/class (2). Manual means there could be human error.

Rikka apps 28 Nov 12, 2022
Highly-available version-controlled service configuration repository based on Git, ZooKeeper and HTTP/2

Visit the official web site for more information. Central Dogma Central Dogma is an open-source, highly-available and version-controlled service confi

LINE 503 Dec 20, 2022
Modern tool for microservice configuration management

Quick start We recommend to start with Microconfig Features guide and then continue reading this documentation. Microconfig overview and features Micr

Microconfig 262 Dec 19, 2022
Get rid of the boilerplate code in properties based configuration.

OWNER OWNER, an API to ease Java property files usage. INTRODUCTION The goal of OWNER API is to minimize the code required to handle application confi

lviggiano 874 Dec 31, 2022
Nacos: Dynamic Naming and Configuration Service

An easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.

Alibaba 25.1k Jan 3, 2023
Simple Java/POJO config library written with love and Lombok

Okaeri Configs Supported platforms (general use) General implementations based on standard format libraries directly. HJSON ?? hjson-java: Human JSON

Okaeri 51 Jan 7, 2023
configuration library for JVM languages using HOCON files

Configuration library for JVM languages. If you have questions or are working on a pull request or just curious, please feel welcome to join the chat

Lightbend 5.8k Jan 4, 2023
Discord4J is a fast, powerful, unopinionated, reactive library to enable quick and easy development of Discord bots for Java, Kotlin, and other JVM languages using the official Discord Bot API.

Discord4J is a fast, powerful, unopinionated, reactive library to enable quick and easy development of Discord bots for Java, Kotlin, and other JVM languages using the official Discord Bot API.

null 1.5k Jan 4, 2023
A library that automatically generates and manages configuration files based on classes.

sc-cfg SC-CFG is a simple, yet powerful library that automatically generate configuration files based on your classes. Compatible with Java 8+ and Kot

null 10 Nov 28, 2022
KickAss Configuration. An annotation-based configuration system for Java and Kotlin

KAConf 2016-2020 Mario Macías KickAss Configuration v0.9.0 is an Annotation-based configuration system inspired in the wonderful Spring Boot. Its stro

Mario Macías 53 Nov 21, 2022
This plugin disables commands specified in the configuration and prevents granting the "OP" authority to people not authorized in the plugin configuration.

Ares This plugin disables commands specified in the configuration and prevents granting the "OP" authority to people not authorized in the plugin conf

ᴠᴀʟᴇɴᴛɪɴ ᴢʜᴇʟᴇᴠ 6 Aug 30, 2022
Apollo is a reliable configuration management system suitable for microservice configuration management scenarios.

English | 中文 Apollo - A reliable configuration management system Apollo is a reliable configuration management system. It can centrally manage the con

Apollo 27.6k Jan 5, 2023
JBehave is a BDD framework for Java and all JVM languages

JBehave is a BDD framework for Java and all JVM languages (Groovy, Kotlin, Ruby, Scala).

null 23 Oct 26, 2022
A Sentry SDK for Java, Android and other JVM languages.

Bad software is everywhere, and we're tired of it. Sentry is on a mission to help developers write better software faster, so we can get back to enjoy

Sentry 912 Dec 28, 2022
JavaOTTF - Official OTTF parser and composer for JVM languages

JavaOTTF Official OTTF parser and composer for JVM languages. Documentation Please refer to the Wiki Section. Installation Maven Add repository into p

Open Timetable 2 Nov 21, 2022