Configuration library for JVM languages using HOCON files
—
Options and customization provide comprehensive control over parsing, resolution, and rendering behavior. The library offers extensive configuration through option classes and extension interfaces for custom includers, resolvers, and loading strategies.
Control configuration parsing behavior with comprehensive options.
public final class ConfigParseOptions {
public static ConfigParseOptions defaults();
public ConfigParseOptions setSyntax(ConfigSyntax syntax);
public ConfigParseOptions setOriginDescription(String originDescription);
public ConfigParseOptions setAllowMissing(boolean allowMissing);
public ConfigParseOptions setClassLoader(ClassLoader loader);
public ConfigParseOptions setIncluder(ConfigIncluder includer);
public ConfigSyntax getSyntax();
public String getOriginDescription();
public boolean getAllowMissing();
public ClassLoader getClassLoader();
public ConfigIncluder getIncluder();
}Usage Examples:
// Parse with specific syntax
ConfigParseOptions jsonOptions = ConfigParseOptions.defaults()
.setSyntax(ConfigSyntax.JSON);
Config config = ConfigFactory.parseString(jsonString, jsonOptions);
// Allow missing files
ConfigParseOptions lenientOptions = ConfigParseOptions.defaults()
.setAllowMissing(true);
Config config = ConfigFactory.parseFile(optionalFile, lenientOptions);
// Custom origin description for debugging
ConfigParseOptions describedOptions = ConfigParseOptions.defaults()
.setOriginDescription("generated config from service discovery");
Config config = ConfigFactory.parseString(dynamicConfig, describedOptions);
// Custom classloader for resource loading
ConfigParseOptions loaderOptions = ConfigParseOptions.defaults()
.setClassLoader(pluginClassLoader);
Config config = ConfigFactory.parseResources("plugin.conf", loaderOptions);Control file format interpretation with ConfigSyntax enum.
public enum ConfigSyntax {
JSON, // Strict JSON format
CONF, // HOCON format (Human-Optimized Config Object Notation)
PROPERTIES // Java Properties format
}Usage Examples:
// Force JSON parsing (strict)
Config jsonConfig = ConfigFactory.parseString(jsonString,
ConfigParseOptions.defaults().setSyntax(ConfigSyntax.JSON));
// Force HOCON parsing (allows comments, includes, etc.)
Config hoconConfig = ConfigFactory.parseString(hoconString,
ConfigParseOptions.defaults().setSyntax(ConfigSyntax.CONF));
// Force Properties parsing
Config propsConfig = ConfigFactory.parseString(propsString,
ConfigParseOptions.defaults().setSyntax(ConfigSyntax.PROPERTIES));
// Auto-detect syntax (default behavior)
Config autoConfig = ConfigFactory.parseString(unknownFormat);Control substitution resolution behavior.
public final class ConfigResolveOptions {
public static ConfigResolveOptions defaults();
public static ConfigResolveOptions noSystem();
public ConfigResolveOptions setUseSystemEnvironment(boolean value);
public ConfigResolveOptions setAllowUnresolved(boolean value);
public ConfigResolveOptions appendResolver(ConfigResolver resolver);
public List<ConfigResolver> getResolvers();
public boolean getUseSystemEnvironment();
public boolean getAllowUnresolved();
}Usage Examples:
// Disable system environment variable resolution
ConfigResolveOptions noEnv = ConfigResolveOptions.defaults()
.setUseSystemEnvironment(false);
Config resolved = config.resolve(noEnv);
// Allow partial resolution (don't fail on unresolved substitutions)
ConfigResolveOptions partial = ConfigResolveOptions.defaults()
.setAllowUnresolved(true);
Config partiallyResolved = config.resolve(partial);
// Completely isolated resolution (no system integration)
ConfigResolveOptions isolated = ConfigResolveOptions.noSystem();
Config resolved = config.resolve(isolated);
// Add custom resolvers
ConfigResolver customResolver = new DatabaseConfigResolver();
ConfigResolveOptions withCustom = ConfigResolveOptions.defaults()
.appendResolver(customResolver);
Config resolved = config.resolve(withCustom);Control configuration rendering to strings.
public final class ConfigRenderOptions {
public static ConfigRenderOptions defaults();
public static ConfigRenderOptions concise();
public ConfigRenderOptions setComments(boolean value);
public ConfigRenderOptions setOriginComments(boolean value);
public ConfigRenderOptions setFormatted(boolean value);
public ConfigRenderOptions setJson(boolean value);
public ConfigRenderOptions setShowEnvVariableValues(boolean value);
public boolean getComments();
public boolean getOriginComments();
public boolean getFormatted();
public boolean getJson();
public boolean getShowEnvVariableValues();
}Usage Examples:
Config config = ConfigFactory.load();
// Default rendering (HOCON with comments and formatting)
String defaultRender = config.root().render();
// Compact JSON (no comments, minimal whitespace)
String json = config.root().render(ConfigRenderOptions.concise().setJson(true));
// Pretty-printed HOCON without comments
String clean = config.root().render(
ConfigRenderOptions.defaults()
.setComments(false)
.setFormatted(true)
);
// Include file/line origin information in comments
String withOrigins = config.root().render(
ConfigRenderOptions.defaults()
.setOriginComments(true)
);
// Hide environment variable values for security
String secure = config.root().render(
ConfigRenderOptions.defaults()
.setShowEnvVariableValues(false)
);Customize how include statements are processed in configuration files.
public interface ConfigIncluder {
ConfigIncluder withFallback(ConfigIncluder fallback);
ConfigObject include(ConfigIncludeContext context, String what);
}Specialized Includer Interfaces:
public interface ConfigIncluderFile extends ConfigIncluder {
ConfigObject includeFile(ConfigIncludeContext context, File what);
}
public interface ConfigIncluderURL extends ConfigIncluder {
ConfigObject includeURL(ConfigIncludeContext context, URL what);
}
public interface ConfigIncluderClasspath extends ConfigIncluder {
ConfigObject includeResources(ConfigIncludeContext context, String what);
}Implementation Examples:
// Custom includer that loads from a database
public class DatabaseIncluder implements ConfigIncluder {
private final ConfigService configService;
public DatabaseIncluder(ConfigService service) {
this.configService = service;
}
@Override
public ConfigObject include(ConfigIncludeContext context, String what) {
try {
String configData = configService.getConfiguration(what);
if (configData != null) {
return ConfigFactory.parseString(configData,
context.parseOptions().setOriginDescription("database:" + what))
.root();
}
} catch (Exception e) {
throw new ConfigException.IO(context.parseOptions().getOriginDescription(),
"Failed to load from database: " + what, e);
}
return null; // Not found
}
@Override
public ConfigIncluder withFallback(ConfigIncluder fallback) {
return new FallbackConfigIncluder(this, fallback);
}
}
// Usage
ConfigIncluder dbIncluder = new DatabaseIncluder(myConfigService);
ConfigParseOptions options = ConfigParseOptions.defaults()
.setIncluder(dbIncluder);
Config config = ConfigFactory.parseString(configWithIncludes, options);Context information available during include processing.
public interface ConfigIncludeContext {
ConfigIncludeContext relativeTo(String filename);
ConfigParseOptions parseOptions();
}Usage in Custom Includers:
@Override
public ConfigObject include(ConfigIncludeContext context, String what) {
// Get parse options from context
ConfigParseOptions options = context.parseOptions();
ClassLoader loader = options.getClassLoader();
// Create relative context for nested includes
ConfigIncludeContext relativeContext = context.relativeTo(what);
// Use context information for resolution
String resolvedPath = resolveRelativePath(what, context);
return loadFromPath(resolvedPath, relativeContext);
}Provide custom substitution value sources.
public interface ConfigResolver {
ConfigValue lookup(String path);
ConfigResolver withFallback(ConfigResolver fallback);
}Implementation Examples:
// Resolver that fetches values from external service
public class ServiceConfigResolver implements ConfigResolver {
private final ConfigurationService service;
private final Map<String, ConfigValue> cache = new ConcurrentHashMap<>();
public ServiceConfigResolver(ConfigurationService service) {
this.service = service;
}
@Override
public ConfigValue lookup(String path) {
return cache.computeIfAbsent(path, this::fetchFromService);
}
private ConfigValue fetchFromService(String path) {
try {
String value = service.getValue(path);
if (value != null) {
return ConfigValueFactory.fromAnyRef(value, "service:" + path);
}
} catch (Exception e) {
// Log but don't fail - allow fallback resolvers
logger.warn("Failed to resolve {} from service", path, e);
}
return null;
}
@Override
public ConfigResolver withFallback(ConfigResolver fallback) {
return new ChainedConfigResolver(this, fallback);
}
}
// Resolver for encrypted values
public class EncryptedConfigResolver implements ConfigResolver {
private final Cipher cipher;
@Override
public ConfigValue lookup(String path) {
// Only handle paths that start with "encrypted."
if (!path.startsWith("encrypted.")) {
return null;
}
try {
String encryptedValue = getEncryptedValue(path);
String decryptedValue = decrypt(encryptedValue);
return ConfigValueFactory.fromAnyRef(decryptedValue, "decrypted:" + path);
} catch (Exception e) {
throw new ConfigException.BadValue(path, "Failed to decrypt value", e);
}
}
}Override the default application configuration loading process.
public interface ConfigLoadingStrategy {
Config parseApplicationConfig(ConfigParseOptions parseOptions);
}Implementation and Usage:
// Custom loading strategy that loads from multiple sources
public class MultiSourceLoadingStrategy implements ConfigLoadingStrategy {
@Override
public Config parseApplicationConfig(ConfigParseOptions parseOptions) {
Config base = ConfigFactory.parseResources("base.conf", parseOptions);
Config environment = loadEnvironmentConfig(parseOptions);
Config secrets = loadSecrets(parseOptions);
return secrets
.withFallback(environment)
.withFallback(base);
}
private Config loadEnvironmentConfig(ConfigParseOptions options) {
String env = System.getProperty("app.environment", "development");
return ConfigFactory.parseResources("environments/" + env + ".conf", options);
}
private Config loadSecrets(ConfigParseOptions options) {
// Load from secure storage
return secretsService.loadConfig(options);
}
}
// Register strategy via system property
System.setProperty("config.strategy",
"com.mycompany.config.MultiSourceLoadingStrategy");
// Strategy will be used automatically by ConfigFactory.load()
Config config = ConfigFactory.load();Many extension interfaces support chaining with fallback behavior.
// Chain includers
ConfigIncluder primary = new DatabaseIncluder(dbService);
ConfigIncluder secondary = new S3Includer(s3Service);
ConfigIncluder fallback = ConfigIncluderFactory.newDefault();
ConfigIncluder chain = primary
.withFallback(secondary)
.withFallback(fallback);
// Chain resolvers
ConfigResolver encrypted = new EncryptedConfigResolver();
ConfigResolver service = new ServiceConfigResolver(configService);
ConfigResolver system = new SystemConfigResolver();
ConfigResolver resolverChain = encrypted
.withFallback(service)
.withFallback(system);Combine multiple extension instances into a single component.
// Composite includer that delegates based on scheme
public class SchemeBasedIncluder implements ConfigIncluder {
private final Map<String, ConfigIncluder> includers = new HashMap<>();
public SchemeBasedIncluder() {
includers.put("http", new HttpIncluder());
includers.put("https", new HttpsIncluder());
includers.put("file", new FileIncluder());
includers.put("classpath", new ClasspathIncluder());
includers.put("database", new DatabaseIncluder());
}
@Override
public ConfigObject include(ConfigIncludeContext context, String what) {
URI uri = URI.create(what);
String scheme = uri.getScheme();
ConfigIncluder includer = includers.get(scheme);
if (includer != null) {
return includer.include(context, what);
}
throw new ConfigException.BadPath(what, "Unsupported include scheme: " + scheme);
}
}Validate configuration after loading and resolution.
public void checkValid(Config reference, String... restrictToPaths);Usage Examples:
// Load reference configuration (schema)
Config reference = ConfigFactory.parseResources("reference.conf");
// Load actual configuration
Config config = ConfigFactory.load().resolve();
// Validate against reference
try {
config.checkValid(reference);
// Configuration is valid
} catch (ConfigException.ValidationFailed e) {
// Handle validation errors
List<ConfigException.ValidationProblem> problems = e.problems();
for (ConfigException.ValidationProblem problem : problems) {
String path = problem.path();
String description = problem.problem();
System.err.println("Validation error at " + path + ": " + description);
}
}
// Validate only specific paths
config.checkValid(reference, "database", "server", "logging");*.defaults() and modify from therewithFallback() to create robust fallback chainscheckValid() to catch configuration errors earlyInstall with Tessl CLI
npx tessl i tessl/maven-com-typesafe--config