### Install GraalVM Native Image Compiler Source: https://github.com/sksamuel/hoplite/blob/master/example-native/README.md Installs the native image compiler for GraalVM. This is a prerequisite for building native executables. ```shell gu install native-image ``` -------------------------------- ### YAML Configuration Example for Prefix Binding Source: https://github.com/sksamuel/hoplite/blob/master/README.md Provides an example of a YAML configuration structure with different modules ('module1', 'module2') and their respective properties. This demonstrates the source data that can be bound using prefixes. ```yaml module1: foo: bar module2: baz: qux ``` -------------------------------- ### Run Native Executable Source: https://github.com/sksamuel/hoplite/blob/master/example-native/README.md Executes the built native binary. This command takes a configuration file as an argument to load application settings. ```shell ./build/native/nativeBuild/example config.yaml ``` -------------------------------- ### Config Loading Error Formatting Example Source: https://github.com/sksamuel/hoplite/blob/master/README.md Presents an example of how Hoplite formats errors when configuration loading fails. The output includes detailed messages about the specific errors, the problematic keys, the expected vs. found types, and the exact location (file and line number) in the configuration source. ```text Error loading config because: - Could not instantiate 'com.sksamuel.hoplite.json.Foo' because: - 'bar': Required type Boolean could not be decoded from a Long (classpath:/error1.json:2:19) - 'baz': Missing from config - 'hostname': Type defined as not-null but null was loaded from config (classpath:/error1.json:6:18) - 'season': Required a value for the Enum type com.sksamuel.hoplite.json.Season but given value was Fun (/home/user/default.json:8:18) - 'users': Defined as a List but a Boolean cannot be converted to a collection (classpath:/error1.json:3:19) - 'interval': Required type java.time.Duration could not be decoded from a String (classpath:/error1.json:7:26) - 'nested': - Could not instantiate 'com.sksamuel.hoplite.json.Wibble' because: - 'a': Required type java.time.LocalDateTime could not be decoded from a String (classpath:/error1.json:10:17) - 'b': Unable to locate a decoder for java.time.LocalTime ``` -------------------------------- ### Build Native Executable with Gradle Source: https://github.com/sksamuel/hoplite/blob/master/example-native/README.md Cleans the build and then builds the native executable using Gradle. This process compiles the application into a self-contained native binary. ```shell ../gradlew clean nativeBuild ``` -------------------------------- ### Random Preprocessor Usage Examples Source: https://github.com/sksamuel/hoplite/blob/master/README.md The random preprocessor replaces placeholder strings with randomly generated values. Examples include integers, doubles, booleans, strings of a specific length, and UUIDs. It's configured directly within the configuration file using specific placeholder formats. ```properties my.number=${random.int} my.bignumber=${random.long} my.uuid=${random.uuid} my.number.less.than.ten=${random.int(10)} my.number.in.range=${random.int[1024,65536]} ``` -------------------------------- ### Update GraalVM Native Image Configurations Source: https://github.com/sksamuel/hoplite/blob/master/example-native/README.md Updates GraalVM native image configurations using Gradle. This command is used to process configuration files, such as 'config.yaml', for the native image build. ```shell ../gradlew run -Dnative.image.agent=1 --args="config.yaml" ``` -------------------------------- ### Overriding Config with System Properties in Hoplite Source: https://github.com/sksamuel/hoplite/blob/master/README.md Shows how to override configuration values using system properties. By prefixing system properties with 'config.override.', you can directly influence specific configuration keys when starting the JVM. ```bash -Dconfig.override.database.name=my_database_name ``` -------------------------------- ### Override Configuration with System Properties in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Explains how to use JVM system properties to override configuration values at runtime with Hoplite. This example shows overriding a nested property defined in a properties file. ```kotlin import com.sksamuel.hoplite.ConfigLoader data class DatabaseConfig(val name: String, val host: String) fun main() { // Start JVM with: -Dconfig.override.database.name=mydb // application.properties contains: database.name=defaultdb val config = ConfigLoader() .loadConfigOrThrow("/application.properties") // database.name will be "mydb" from system property println("Database: ${config.name}") } ``` -------------------------------- ### Define Configuration Data Classes in Kotlin Source: https://github.com/sksamuel/hoplite/blob/master/README.md Define your configuration structure using Kotlin data classes. This example shows nested data classes for database and server configurations, along with a top-level config class. ```kotlin data class Database(val host: String, val port: Int, val user: String, val pass: String) data class Server(val port: Int, val redirectUrl: String) data class Config(val env: String, val database: Database, val server: Server) ``` -------------------------------- ### Implement Reloadable Configuration with Fixed Interval Watcher (Kotlin) Source: https://github.com/sksamuel/hoplite/blob/master/README.md Provides a Kotlin example of setting up a reloadable configuration using Hoplite's `ReloadableConfig`. This snippet configures the reloader to refresh the `TestConfig` every 10 seconds using a `FixedIntervalWatchable`. ```kotlin // create a watchable that will trigger every 10 seconds val watcher = FixedIntervalWatchable(10.seconds) // create our config loader which will parse config when invoked val loader = ConfigLoaderBuilder.default() .addSource(PropertySource.resource("/application.yml")) .build() // create the reloader, adding the watcher, the config loader, and specifying the target config class val reloader = ReloadableConfig(loader, TestConfig::class) .addWatcher(watcher) // obtain the latest config whenever we want reloader.getLatest() // or subscribe for notifications: (TestConfig) -> Unit reloader.subscribe { println("New config!: $it") } ``` -------------------------------- ### Register Custom Parsers in Hoplite (Kotlin) Source: https://context7.com/sksamuel/hoplite/llms.txt Shows how to register custom file extensions with existing parsers or add entirely new format parsers in Hoplite. This example registers the '.data' extension to use the YAML parser. It requires the hoplite library, a data class, and a parser implementation like YamlParser. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder import com.sksamuel.hoplite.parsers.YamlParser data class Config(val name: String) fun main() { // Register .data extension to use YAML parser val config = ConfigLoaderBuilder.default() .addParser("data", YamlParser) .addResourceSource("/application.data") .build() .loadConfigOrThrow() println("Name: ${config.name}") } ``` -------------------------------- ### Hoplite Support for Multiple Configuration File Formats (Kotlin) Source: https://context7.com/sksamuel/hoplite/llms.txt Illustrates how Hoplite can load configuration from various file formats including JSON, YAML, TOML, HOCON, and Properties. It also shows how to mix these formats in a configuration cascade, where later files can override settings from earlier ones. Requires the hoplite library and data classes. ```kotlin import com.sksamuel.hoplite.ConfigLoader data class AppConfig( val name: String, val port: Int, val enabled: Boolean ) fun main() { // config.json val fromJson = ConfigLoader().loadConfigOrThrow("/config.json") // config.yaml val fromYaml = ConfigLoader().loadConfigOrThrow("/config.yaml") // config.toml val fromToml = ConfigLoader().loadConfigOrThrow("/config.toml") // config.conf (HOCON) val fromHocon = ConfigLoader().loadConfigOrThrow("/config.conf") // config.properties val fromProps = ConfigLoader().loadConfigOrThrow("/config.properties") // Mix formats in cascade val mixed = ConfigLoader().loadConfigOrThrow( "/overrides.json", // JSON overrides "/base.yaml" // YAML defaults ) } ``` -------------------------------- ### Load Configuration from String, Map, and Stream in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Demonstrates how to load configuration into a data class from in-memory sources like strings, maps, and input streams using Hoplite. This is useful for testing or dynamic configuration scenarios without relying on external files. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder import com.sksamuel.hoplite.PropertySource data class TestConfig(val a: String, val b: Int, val other: List) fun main() { // From string properties val configFromString = ConfigLoaderBuilder.default() .addPropertySource( PropertySource.string( """ a = hello b = 42 other = value1, value2 """.trimIndent(), "props" ) ) .build() .loadConfigOrThrow() // From map val configFromMap = ConfigLoaderBuilder.default() .addPropertySource( PropertySource.map( mapOf( "a" to "world", "b" to "99", "other" to listOf("x", "y", "z") ) ) ) .build() .loadConfigOrThrow() // From input stream val stream = ""{"a": "stream", "b": 123, "other": ["s1", "s2"]}""" .byteInputStream(Charsets.UTF_8) val configFromStream = ConfigLoaderBuilder.default() .addPropertySource(PropertySource.stream(stream, "json")) .build() .loadConfigOrThrow() println("String config: $configFromString") println("Map config: $configFromMap") println("Stream config: $configFromStream") } ``` -------------------------------- ### Load Configuration with ConfigLoader Source: https://github.com/sksamuel/hoplite/blob/master/README.md Demonstrates how to build and use ConfigLoader to load configuration into a data class. It shows adding resource sources and then loading the configuration, throwing an exception on failure. Dependencies include the Hoplite library. ```kotlin ConfigLoaderBuilder.default() .addResourceSource("/application-prod.yml") .addResourceSource("/reference.json") .build() .loadConfigOrThrow() ``` -------------------------------- ### Build ConfigLoader with Resource Source Source: https://github.com/sksamuel/hoplite/blob/master/README.md Demonstrates building a ConfigLoader with a specific resource on the classpath. This approach allows for more control, such as marking a resource as optional. ```kotlin ConfigLoaderBuilder.default() .addResourceSource("/config.json") .build() .loadConfigOrThrow() ``` -------------------------------- ### Bind Multiple Prefixes to Config Classes with ConfigBinder Source: https://context7.com/sksamuel/hoplite/llms.txt Demonstrates how to use ConfigBinder to load configuration sources once and bind multiple prefixes to different configuration data classes. This improves performance in modular applications by parsing configuration only once. It supports nested paths via dot notation. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder data class Module1Config(val foo: String) data class Module2Config(val baz: String) fun main() { // Configuration parsed only once val configBinder = ConfigLoaderBuilder.default() .addResourceSource("/application.yaml") .build() .configBinder() // Bind different prefixes to different modules val module1Config = configBinder.bindOrThrow("module1") val module2Config = configBinder.bindOrThrow("module2") // Access nested paths with dot notation data class NestedConfig(val value: String) val nestedConfig = configBinder.bindOrThrow("foo.bar.baz") println("Module 1: $module1Config") println("Module 2: $module2Config") println("Nested: $nestedConfig") } ``` -------------------------------- ### Load Modular Configuration with Prefixes in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Demonstrates how to load specific subtrees of a configuration into independent data classes using prefixes with Hoplite. This promotes modularity by isolating configuration sections. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder import com.sksamuel.hoplite.PropertySource data class Module1Config(val foo: String) data class Module2Config(val baz: String) fun main() { // application.yaml contains: // module1: // foo: bar // module2: // baz: qux // Load with prefix parameter val module1Config = ConfigLoaderBuilder.default() .addResourceSource("/application.yaml") .build() .loadConfigOrThrow(prefix = "module1") val module2Config = ConfigLoaderBuilder.default() .addResourceSource("/application.yaml") .build() .loadConfigOrThrow(prefix = "module2") println("Module 1: ${module1Config.foo}") // bar println("Module 2: ${module2Config.baz}") // qux } ``` -------------------------------- ### Load Configuration from Command Line Arguments in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Shows how to use Hoplite to parse command-line arguments as a configuration source. It supports repeated arguments for list types and automatically maps them to the corresponding data class properties. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder import com.sksamuel.hoplite.PropertySource data class TestConfig(val a: String, val b: Int, val other: List) fun main(args: Array) { // Command line: --a="hello world" --b=42 --other=val1 --other=val2 val arguments = arrayOf( "--a=hello world", "--b=42", "--other=val1", "--other=val2" ) val config = ConfigLoaderBuilder.default() .addPropertySource(PropertySource.commandLine(arguments)) .build() .loadConfigOrThrow() println("a: ${config.a}") println("b: ${config.b}") println("other: ${config.other}") // [val1, val2] } ``` -------------------------------- ### Add Custom Preprocessor using withPreprocessor Source: https://github.com/sksamuel/hoplite/blob/master/README.md Demonstrates how to add a custom preprocessor to the ConfigLoader. This involves creating an instance of the `Preprocessor` interface and passing it to the `withPreprocessor` function. ```java ConfigLoader configLoader = ConfigLoader.builder() .withPreprocessor(new MyCustomPreprocessor()) .build(); ``` -------------------------------- ### Bind Configuration by Prefix with ConfigBinder Source: https://github.com/sksamuel/hoplite/blob/master/README.md Illustrates how to use ConfigBinder to bind specific sections of configuration to independent data classes using prefixes. This is useful for modular configuration loading. It requires a ConfigLoader instance and defines data classes for each module's configuration. ```kotlin val configBinder = ConfigLoaderBuilder.default() .addResourceSource("/application-prod.yml") .addResourceSource("/reference.json") .build() .configBinder() val module1Config = configBinder.bindOrThrow("module1") val module2Config = configBinder.bindOrThrow("module2") ``` -------------------------------- ### Build ConfigLoader with Optional Resource Source: https://github.com/sksamuel/hoplite/blob/master/README.md Illustrates building a ConfigLoader where a resource can be optional. If the optional resource is not found, the loading process continues with the other specified resources. ```kotlin ConfigLoaderBuilder.default() .addResourceSource("/missing.yml", optional = true) .addResourceSource("/config.json") .build() .loadConfigOrThrow() ``` -------------------------------- ### Load Cascading Configuration Files Source: https://context7.com/sksamuel/hoplite/llms.txt Loads configuration by layering multiple files, enabling fallback resolution. Values are loaded from specified files in order, with earlier files taking precedence over later ones. Useful for managing default and environment-specific settings. ```kotlin import com.sksamuel.hoplite.ConfigLoader data class ElasticsearchConfig( val host: String, val port: Int, val clusterName: String ) data class Config(val elasticsearch: ElasticsearchConfig) fun main() { // application-prod.yaml contains: // elasticsearch: // host: prd-elasticsearch.scv // port: 8200 // application.yaml contains: // elasticsearch: // port: 9200 // clusterName: product-search val config = ConfigLoader() .loadConfigOrThrow( "/application-prod.yaml", "/application.yaml" ) // Result: host=prd-elasticsearch.scv (from prod), // port=8200 (from prod overrides default), // clusterName=product-search (from default only) println("Host: ${config.elasticsearch.host}") println("Port: ${config.elasticsearch.port}") println("Cluster: ${config.elasticsearch.clusterName}") } ``` -------------------------------- ### Load Configuration from a Resource File in Kotlin Source: https://github.com/sksamuel/hoplite/blob/master/README.md This Kotlin code demonstrates how to load configuration into a defined data class from a resource file. It uses `ConfigLoaderBuilder` to specify the resource and `loadConfigOrThrow` to parse and return the configuration. Errors during loading will result in an exception. ```kotlin val config = ConfigLoaderBuilder.default() .addResourceSource("/application-staging.yml") .build() .loadConfigOrThrow() ``` -------------------------------- ### Load Configuration with Cascading Files Source: https://github.com/sksamuel/hoplite/blob/master/README.md Loads configuration from multiple files, demonstrating cascading. The loader attempts to resolve properties from the files in the order they are provided, with earlier files taking precedence. ```kotlin val config = ConfigLoader.load("prod.json", "default.json") println(config) ``` -------------------------------- ### Type-Safe Wrappers with Inline Classes Source: https://context7.com/sksamuel/hoplite/llms.txt Demonstrates using inline classes to create type-safe wrappers for primitive types without introducing nested configuration keys. This enhances type safety by allowing custom types like Port and Hostname to be directly mapped from configuration values. ```kotlin import com.sksamuel.hoplite.ConfigLoader @JvmInline value class Port(val value: Int) @JvmInline value class Hostname(val value: String) data class Database(val port: Port, val host: Hostname) fun main() { // config.yaml contains: // port: 9200 // host: localhost val config = ConfigLoader().loadConfigOrThrow("/config.yaml") println("Port: ${config.port.value}") // 9200 println("Host: ${config.host.value}") // localhost } ``` -------------------------------- ### Load Configuration with loadConfigOrThrow Source: https://context7.com/sksamuel/hoplite/llms.txt Loads configuration from a classpath resource or file into a type-safe data class. Throws an exception with detailed error messages if configuration resolution fails. Supports basic data structures and Secret types for sensitive values. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.Secret data class Database( val host: String, val port: Int, val user: String, val password: Secret ) data class Server(val port: Int, val redirectUrl: String) data class Config( val env: String, val database: Database, val server: Server ) fun main() { // Load from classpath resource val config = ConfigLoader().loadConfigOrThrow("/application.yaml") // Access type-safe configuration println("Environment: ${config.env}") println("Database: ${config.database.host}:${config.database.port}") println("Server port: ${config.server.port}") // Password is masked: prints "****" println("Password: ${config.database.password}") // Access actual password value val actualPassword = config.database.password.value } ``` -------------------------------- ### Override Configuration with Environment Variables in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Illustrates how to override configuration values using environment variables with Hoplite. It demonstrates automatic mapping of underscores to nested properties and support for array indices. ```kotlin import com.sksamuel.hoplite.ConfigLoader import io.kotest.extensions.system.withEnvironment data class Bar(val s: Long, val t: Long) data class Foo(val bar: Bar) data class TestConfig(val foo: Foo) fun main() { // sysproptest2.json contains: // { "foo": { "bar": { "s": 5, "t": 6 } } } // Environment variable FOO_BAR_S overrides the nested value withEnvironment(mapOf("FOO_BAR_S" to "1")) { val config = ConfigLoader() .loadConfigOrThrow("/sysproptest2.json") // Result: s=1 (from env var), t=6 (from file) println("s: ${config.foo.bar.s}") // 1 println("t: ${config.foo.bar.t}") // 6 } // Array support with indices // Set env vars: TOPIC_NAME_0=first TOPIC_NAME_1=second data class TopicConfig(val name: List) withEnvironment( mapOf( "TOPIC_NAME_0" to "first", "TOPIC_NAME_1" to "second" ) ) { val topicConfig = ConfigLoader().loadConfigOrThrow() println("Topics: ${topicConfig.name}") // [first, second] } } ``` -------------------------------- ### Environment Variable Substitution in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Utilizes Hoplite's preprocessor to substitute placeholders in configuration files with environment variables or system properties. It supports default values using the `:-` syntax. This requires the `hoplite-core` dependency and processes string inputs, outputting a configuration object with resolved values. ```kotlin import com.sksamuel.hoplite.ConfigLoader data class Config( val greeting: String, val port: Int, val debug: Boolean ) fun main() { // config.yaml contains: // greeting: "hello ${USERNAME}" // port: ${PORT:-8080} // debug: ${DEBUG} // Set environment variables: // USERNAME=sam // DEBUG=true // (PORT is not set, so default 8080 will be used) val config = ConfigLoader().loadConfigOrThrow("/config.yaml") // Results: println(config.greeting) // "hello sam" println(config.port) // 8080 (default) println(config.debug) // true } ``` -------------------------------- ### Build Custom Loaders with ConfigLoaderBuilder Source: https://context7.com/sksamuel/hoplite/llms.txt Constructs specialized configuration loaders using `ConfigLoaderBuilder`. Allows defining multiple configuration sources (resources, files) with precedence rules, enabling optional files and enabling strict mode to detect unused configuration keys. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder import com.sksamuel.hoplite.PropertySource import com.sksamuel.hoplite.addResourceSource import com.sksamuel.hoplite.addFileSource data class AppConfig( val name: String, val database: DatabaseConfig, val features: Map ) data class DatabaseConfig( val host: String, val port: Int, val poolSize: Int = 10 ) fun main() { val config = ConfigLoaderBuilder.default() // Environment-specific config takes precedence .addResourceSource("/application-prod.yml") // Base configuration provides defaults .addResourceSource("/application.yml") // Allow optional local overrides .addFileSource("local.properties", optional = true) // Enable strict mode to detect unused config keys .strict() .build() .loadConfigOrThrow() println("App: ${config.name}") println("Database pool size: ${config.database.poolSize}") println("Features enabled: ${config.features.filter { it.value }}") } ``` -------------------------------- ### Environment Variable Mapping in Hoplite Source: https://github.com/sksamuel/hoplite/blob/master/README.md Illustrates how environment variables are mapped to configuration properties in Hoplite. Underscores separate nested properties, and suffixes like _0, _1, or _FOO, _BAR are used for arrays/lists and maps respectively. ```text TOPIC_NAME -> topic.name TOPIC_NAME_0 -> topic.name[0] TOPIC_NAME_FOO -> topic.name.foo ``` -------------------------------- ### Load Configuration from JSON Resource Source: https://github.com/sksamuel/hoplite/blob/master/README.md Loads configuration from a JSON resource file on the classpath. This method automatically adds the resource as a property source to the configuration loader. ```kotlin ConfigLoader().loadConfigOrThrow("/config.json") ``` -------------------------------- ### Configure Repeated Preprocessor Application Source: https://github.com/sksamuel/hoplite/blob/master/README.md Shows how to configure Hoplite to apply preprocessors multiple times. This is useful when one preprocessor's output needs to be processed by another preprocessor. ```java ConfigLoader configLoader = ConfigLoader.builder() .withPreprocessingIterations(3) // Apply all preprocessors 3 times .build(); ``` -------------------------------- ### Use ConfigAlias for Field Migration in Hoplite (Kotlin) Source: https://context7.com/sksamuel/hoplite/llms.txt Demonstrates using the @ConfigAlias annotation in Hoplite to support multiple configuration key names for the same field, facilitating gradual migration of configuration files. This allows existing keys to be recognized alongside new ones. It requires the hoplite library and Kotlin data classes with the annotation. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.ConfigAlias data class Database( @ConfigAlias("host") val hostname: String, @ConfigAlias("port") val portNumber: Int ) data class Config(val database: Database) fun main() { // Old config with legacy names: // old-config.yaml contains: // database: // host: localhost // port: 3306 val oldConfig = ConfigLoader().loadConfigOrThrow("/old-config.yaml") println("Host: ${oldConfig.database.hostname}") // localhost // New config with new names: // new-config.yaml contains: // database: // hostname: localhost // portNumber: 3306 val newConfig = ConfigLoader().loadConfigOrThrow("/new-config.yaml") println("Host: ${newConfig.database.hostname}") // localhost // Both work! Allows gradual migration } ``` -------------------------------- ### Polymorphic Configuration with Sealed Classes Source: https://context7.com/sksamuel/hoplite/llms.txt Illustrates using sealed classes to handle polymorphic configuration. Hoplite automatically selects the correct implementation based on the available keys in the configuration file. This is useful for configurations with different variants, such as database connections. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.Secret sealed class Database { data class Mysql( val host: String, val port: Int, val user: String, val pass: Secret ) : Database() data class Elastic( val host: String, val port: Int, val clusterName: String ) : Database() object Embedded : Database() } data class Config(val database: Database) fun main() { // mysql.json contains: // { "database": { "host": "localhost", "port": 3306, "user": "root", "pass": "secret" } } val mysqlConfig = ConfigLoader().loadConfigOrThrow("/mysql.json") when (val db = mysqlConfig.database) { is Database.Mysql -> println("MySQL at ${db.host}:${db.port}") is Database.Elastic -> println("Elasticsearch at ${db.host}:${db.port}") is Database.Embedded -> println("Embedded database") } // elastic.json contains: // { "database": { "host": "es.local", "port": 9200, "clusterName": "prod" } } val elasticConfig = ConfigLoader().loadConfigOrThrow("/elastic.json") // embedded.json contains: { "database": "Embedded" } // or: { "database": {} } val embeddedConfig = ConfigLoader().loadConfigOrThrow("/embedded.json") } ``` -------------------------------- ### Configuring Sealed Classes with Hoplite Source: https://github.com/sksamuel/hoplite/blob/master/README.md Hoplite supports the configuration of sealed classes by matching provided configuration keys to the parameters of the sealed class's implementations. If configuration keys uniquely match an implementation, Hoplite instantiates it. If keys match multiple implementations, the first match is used. Mismatched keys will result in a loading failure. ```kotlin sealed class Database { data class Elasticsearch(val host: String, val port: Int, val index: String) : Database() data class Postgres(val host: String, val port: Int, val schema: String, val table: String) : Database() } data class TestConfig(val databases: List) ``` ```yaml databases: - host: localhost port: 9200 index: foo - host: localhost port: 9300 index: bar - host: localhost port: 5234 schema: public table: faz ``` ```kotlin val config = ConfigLoader().loadConfigOrThrow("config.file") println(config) ``` -------------------------------- ### Use Objects in Sealed Classes with Hoplite (Kotlin) Source: https://github.com/sksamuel/hoplite/blob/master/README.md Demonstrates how Hoplite supports using object subclasses within sealed classes. This allows for configuration of specific object instances or lists containing them. It shows how to reference these objects by type name in YAML/JSON or by an empty object in JSON. ```kotlin sealed class Database { data class Elasticsearch(val host: String, val port: Int, val index: String) : Database() data class Postgres(val host: String, val port: Int, val schema: String, val table: String) : Database() object Embedded : Database() } data class TestConfig(val databases: List) ``` -------------------------------- ### Data Classes for Prefix Binding Source: https://github.com/sksamuel/hoplite/blob/master/README.md Defines simple Kotlin data classes, `Module1Config` and `Module2Config`, which correspond to the configuration sections defined by prefixes 'module1' and 'module2' respectively. These classes are used with `ConfigBinder`. ```kotlin data class Module1Config(val foo: String) data class Module2Config(val baz: String) ``` -------------------------------- ### Lookup Preprocessor for Config References in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Implements a lookup preprocessor in Hoplite to reference other configuration values within the same file, preventing duplication. It uses double curly braces `{{...}}` for interpolation. This requires the `hoplite-core` dependency and processes string inputs, outputting a configuration object with resolved cross-references. ```kotlin import com.sksamuel.hoplite.ConfigLoader data class ServiceConfig( val primaryUrl: String, val backupUrl: String, val monitoringUrl: String ) data class Config( val baseUrl: String, val services: ServiceConfig ) fun main() { // config.yaml contains: // baseUrl: "https://example.com" // services: // primaryUrl: "{{baseUrl}}/api/v1" // backupUrl: "{{baseUrl}}/api/v1/backup" // monitoringUrl: "{{baseUrl}}/health" val config = ConfigLoader().loadConfigOrThrow("/config.yaml") println(config.services.primaryUrl) // https://example.com/api/v1 println(config.services.backupUrl) // https://example.com/api/v1/backup println(config.services.monitoringUrl) // https://example.com/health } ``` -------------------------------- ### Azure Key Vault Preprocessor Configuration Source: https://github.com/sksamuel/hoplite/blob/master/README.md This preprocessor replaces strings prefixed with 'azurekeyvault://' by retrieving their values from Azure Key Vault. It requires the 'hoplite-azure' module to be added to the classpath. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.azure.AzureKeyVaultPreprocessor val config = ConfigLoader.Builder() .addPreprocessor(AzureKeyVaultPreprocessor()) .loadConfig() ``` -------------------------------- ### Consul Configuration Preprocessor Configuration Source: https://github.com/sksamuel/hoplite/blob/master/README.md This preprocessor replaces strings prefixed with 'consul://' by retrieving their values from a Consul server. It requires the 'hoplite-consul' module to be added to the classpath. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.consul.ConsulConfigPreprocessor val config = ConfigLoader.Builder() .addPreprocessor(ConsulConfigPreprocessor()) .loadConfig() ``` -------------------------------- ### Add YAML String Property Source Source: https://github.com/sksamuel/hoplite/blob/master/README.md Adds a YAML string as a property source. This allows for defining configurations using YAML syntax directly within the code. ```kotlin ConfigLoaderBuilder.default() .addSource(YamlPropertySource( """ database: "localhost" port: 1234 """)) .build() .loadConfigOrThrow() ``` -------------------------------- ### Random Value Generation in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Leverages Hoplite's preprocessor to generate random values (UUID, integers within a range, random strings) at configuration load time. This is useful for testing or generating unique identifiers. It requires the `hoplite-core` dependency and processes string inputs, outputting a configuration object populated with generated random data. ```kotlin import com.sksamuel.hoplite.ConfigLoader data class TestConfig( val testId: String, val randomPort: Int, val uniqueToken: String ) fun main() { // config.yaml contains: // testId: "test-${random.uuid}" // randomPort: ${random.int(10000, 20000)} // uniqueToken: ${random.string(32)} val config = ConfigLoader().loadConfigOrThrow("/config.yaml") // Each load generates new random values println("Test ID: ${config.testId}") // test-550e8400-e29b-41d4-a716-446655440000 println("Random port: ${config.randomPort}") // Random int between 10000-20000 println("Token: ${config.uniqueToken}") // 32-character alphanumeric string } ``` -------------------------------- ### Mix Embedded and Specific Objects in YAML List (Hoplite) Source: https://github.com/sksamuel/hoplite/blob/master/README.md Demonstrates how to configure a list of `Database` types in YAML, mixing the `Embedded` object with a specific `Elasticsearch` configuration using Hoplite. ```yaml databases: - "Embedded" - host: localhost port: 9300 index: bar ``` -------------------------------- ### Add JSON String Property Source Source: https://github.com/sksamuel/hoplite/blob/master/README.md Adds a JSON string directly as a property source to the configuration loader. This is useful for inline configurations or dynamic JSON data. ```kotlin ConfigLoaderBuilder.default() .addSource(JsonPropertySource( ``` -------------------------------- ### Add TOML String Property Source Source: https://github.com/sksamuel/hoplite/blob/master/README.md Adds a TOML string as a property source. This enables the use of TOML formatted configurations directly in the code. ```kotlin ConfigLoaderBuilder.default() .addSource(TomlPropertySource( """ database = "localhost" port = 1234 """')) .build() .loadConfigOrThrow() ``` -------------------------------- ### Registering Custom File Extension for Yaml Parser in Hoplite Source: https://github.com/sksamuel/hoplite/blob/master/README.md This snippet demonstrates how to register a custom file extension (e.g., '.data') with an existing parser (YamlParser) using the ConfigLoaderBuilder. This allows Hoplite to parse configuration files with non-default extensions. ```java ConfigLoaderBuilder.default().addParser("data", YamlParser).build() ``` -------------------------------- ### AWS Systems Manager Parameter Store Preprocessor Configuration Source: https://github.com/sksamuel/hoplite/blob/master/README.md This preprocessor replaces strings prefixed with '${ssm:' by retrieving their values from AWS Systems Manager Parameter Store. It requires the 'hoplite-aws' module to be added to the classpath. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.aws.ParameterStorePreprocessor val config = ConfigLoader.Builder() .addPreprocessor(ParameterStorePreprocessor()) .loadConfig() ``` -------------------------------- ### Handling Sensitive Values with the Secret Type Source: https://context7.com/sksamuel/hoplite/llms.txt Shows how to use the Secret type to wrap sensitive configuration values. This prevents accidental logging or display of sensitive data while still allowing programmatic access to the actual value when needed, such as for authentication. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.Secret data class DatabaseConfig( val host: String, val password: Secret, val apiKey: Secret ) fun main() { // config.toml contains: // host = "localhost" // password = "my-secret-password" // apiKey = "api-key-12345" val config = ConfigLoader().loadConfigOrThrow("/config.toml") // toString() is masked println(config) // DatabaseConfig(host=localhost, password=****, apiKey=****) // Access actual values when needed val actualPassword = config.password.value // "my-secret-password" val actualApiKey = config.apiKey.value // "api-key-12345" // Use in authentication connectToDatabase(config.host, config.password.value) } fun connectToDatabase(host: String, password: String) { println("Connecting to $host...") } ``` -------------------------------- ### Add Java Properties Object Property Source Source: https://github.com/sksamuel/hoplite/blob/master/README.md Adds a java.util.Properties object as a property source. This is convenient for integrating with existing Java Properties objects. ```kotlin ConfigLoaderBuilder.default() .addSource(PropsPropertySource(myProps)) .build() .loadConfigOrThrow() ``` -------------------------------- ### Hoplite Parameter Mappers for Case Conversion Source: https://github.com/sksamuel/hoplite/blob/master/README.md Illustrates how Hoplite's `ParameterMapper` interface allows for modifying parameter names before lookup. This enables using different casing conventions (like snake_case or kebab-case) for configuration keys than the field names in data classes. Hoplite automatically registers `KebabCaseParamMapper` and `SnakeCaseParamMapper`. ```kotlin data class Database(val instanceHostName: String) ``` -------------------------------- ### Decode Standard Types and Collections in Kotlin Source: https://context7.com/sksamuel/hoplite/llms.txt Loads and decodes various standard data types and collections (primitives, lists, sets, maps, dates, custom types) from a JSON configuration file into a Kotlin data class. It requires the `hoplite-core` dependency and handles JSON input, outputting a strongly-typed configuration object. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.SizeInBytes import java.time.LocalDateTime import java.time.Duration import java.math.BigDecimal import kotlin.time.Duration.Companion.seconds data class ComplexConfig( // Basic types val name: String, val port: Int, val enabled: Boolean, val ratio: Double, // Collections val tags: List, val features: Set, val metadata: Map, // Java time types val created: LocalDateTime, val timeout: Duration, // Specialized types val maxMemory: SizeInBytes, val bigValue: BigDecimal, // Nullable with default val optional: String? = null ) fun main() { // config.json contains: // { // "name": "myapp", // "port": 8080, // "enabled": true, // "ratio": 0.75, // "tags": ["prod", "api"], // "features": ["auth", "logging"], // "metadata": {"version": "1.0", "region": "us-east-1"}, // "created": "2025-01-01T10:00:00", // "timeout": "30 seconds", // "maxMemory": "512MiB", // "bigValue": "999999999999.99" // } val config = ConfigLoader().loadConfigOrThrow("/config.json") println("App: ${config.name} on port ${config.port}") println("Tags: ${config.tags}") println("Memory limit: ${config.maxMemory.bytes} bytes") println("Timeout: ${config.timeout.seconds} seconds") } ``` -------------------------------- ### Enable Strict Mode in Hoplite for Unused Keys (Kotlin) Source: https://context7.com/sksamuel/hoplite/llms.txt Enables strict mode in Hoplite to fail fast if configuration files contain keys not mapped to any data class fields. This helps in catching typos and unused configurations early. It requires the hoplite library and basic Kotlin data class definitions. ```kotlin import com.sksamuel.hoplite.ConfigLoaderBuilder data class DatabaseConfig( val host: String, val port: Int ) data class Config(val database: DatabaseConfig) fun main() { // config-with-typo.yaml contains: // database: // host: localhost // port: 3306 // username: root # This key is not in DatabaseConfig // prot: 5432 # Typo: should be port try { val config = ConfigLoaderBuilder.default() .addResourceSource("/config-with-typo.yaml") .strict() // Enable strict mode .build() .loadConfigOrThrow() } catch (e: Exception) { // Will throw exception with details: // Error loading config because: // Config value 'username' at (classpath:/config-with-typo.yaml:4:14) was unused // Config value 'prot' at (classpath:/config-with-typo.yaml:5:10) was unused println(e.message) } } ``` -------------------------------- ### Using Kotlin Inline Classes with Hoplite for Strong Typing Source: https://github.com/sksamuel/hoplite/blob/master/README.md Hoplite seamlessly supports Kotlin's inline classes, allowing for strong typing without nested configuration keys. This improves code clarity and type safety by wrapping simple values like Int or String into dedicated types, such as Port or Hostname. ```kotlin inline class Port(val value: Int) inline class Hostname(val value: String) data class Database(val port: Port, val host: Hostname) ``` ```yaml port: 9200 host: localhost ``` ```kotlin val config = ConfigLoader().loadConfigOrThrow("config.file") println(config.port) // Port(9200) println(config.host) // Hostname("localhost") ``` -------------------------------- ### Use @ConfigAlias for Field Renaming in Hoplite Source: https://github.com/sksamuel/hoplite/blob/master/README.md Demonstrates how to use the `@ConfigAlias` annotation in Hoplite to allow a configuration field to accept multiple names. This is useful for refactoring config classes without needing to update all configuration files. ```kotlin data class Database(@ConfigAlias("host") val hostname: String) data class MyConfig(val database: Database) ``` -------------------------------- ### Add Hoplite Dependency to Gradle Build Source: https://github.com/sksamuel/hoplite/blob/master/README.md This code snippet shows how to add the Hoplite core dependency to your Gradle build file. You will also need to include a module for the configuration format(s) you intend to use. ```groovy implementation 'com.sksamuel.hoplite:hoplite-core:' ``` -------------------------------- ### Mix Embedded and Specific Objects in JSON List (Hoplite) Source: https://github.com/sksamuel/hoplite/blob/master/README.md Shows the JSON syntax for configuring a list of `Database` types, including the `Embedded` object and a specific `Elasticsearch` configuration, when using Hoplite. ```json { "databases": ["Embedded", { "host": "localhost", "port": 9200, "index": "foo" }] } ``` -------------------------------- ### GCP Secret Manager Preprocessor Configuration Source: https://github.com/sksamuel/hoplite/blob/master/README.md This preprocessor replaces strings with the format 'gcpsm://projects/{projectId}/secrets/{secretName}/versions/{version:latest}' by retrieving values from Google Cloud Secret Manager. It requires the 'hoplite-gcp' module to be added to the classpath. ```kotlin import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.gcp.GcpSecretManagerPreprocessor val config = ConfigLoader.Builder() .addPreprocessor(GcpSecretManagerPreprocessor()) .loadConfig() ```