or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdconfig.mdengine.mdindex.mdplugins.mdrequest.mdresponse.mdrouting.md

config.mddocs/

0

# Configuration Management

1

2

Hierarchical configuration system with type conversion, environment-specific settings, and support for multiple configuration sources including files, environment variables, and programmatic configuration.

3

4

## Capabilities

5

6

### Application Configuration

7

8

Core interface for accessing application configuration with hierarchical property access and type conversion.

9

10

```kotlin { .api }

11

/**

12

* Interface for application configuration access

13

*/

14

interface ApplicationConfig {

15

/** Get configuration property by path */

16

fun property(path: String): ApplicationConfigValue

17

/** Get optional configuration property */

18

fun propertyOrNull(path: String): ApplicationConfigValue?

19

/** Get nested configuration section */

20

fun config(path: String): ApplicationConfig

21

/** Get list of configuration sections */

22

fun configList(path: String): List<ApplicationConfig>

23

/** Get all configuration keys at current level */

24

fun keys(): Set<String>

25

/** Convert configuration to map */

26

fun toMap(): Map<String, Any?>

27

}

28

29

/**

30

* Configuration value with type conversion

31

*/

32

interface ApplicationConfigValue {

33

/** Get value as string */

34

fun getString(): String

35

/** Get value as list of strings */

36

fun getList(): List<String>

37

}

38

39

/** Access configuration from application call */

40

val ApplicationCall.config: ApplicationConfig get() = application.environment.config

41

```

42

43

### Configuration Value Extensions

44

45

Extension functions for type-safe configuration value access with default values and validation.

46

47

```kotlin { .api }

48

/**

49

* Get configuration value as Int

50

* @param default - Default value if property not found or conversion fails

51

* @return Integer value or default

52

*/

53

fun ApplicationConfigValue.getInt(default: Int = 0): Int = try {

54

getString().toInt()

55

} catch (e: Exception) {

56

default

57

}

58

59

/**

60

* Get configuration value as Long

61

*/

62

fun ApplicationConfigValue.getLong(default: Long = 0L): Long = try {

63

getString().toLong()

64

} catch (e: Exception) {

65

default

66

}

67

68

/**

69

* Get configuration value as Boolean

70

*/

71

fun ApplicationConfigValue.getBoolean(default: Boolean = false): Boolean = try {

72

getString().toBoolean()

73

} catch (e: Exception) {

74

default

75

}

76

77

/**

78

* Get configuration value as Double

79

*/

80

fun ApplicationConfigValue.getDouble(default: Double = 0.0): Double = try {

81

getString().toDouble()

82

} catch (e: Exception) {

83

default

84

}

85

86

/**

87

* Get required configuration value as Int

88

* @throws ConfigurationException if property not found or conversion fails

89

*/

90

fun ApplicationConfigValue.getIntOrFail(): Int = try {

91

getString().toInt()

92

} catch (e: Exception) {

93

throw ConfigurationException("Cannot convert configuration value to Int", e)

94

}

95

96

/**

97

* Get required configuration value as Long

98

*/

99

fun ApplicationConfigValue.getLongOrFail(): Long = try {

100

getString().toLong()

101

} catch (e: Exception) {

102

throw ConfigurationException("Cannot convert configuration value to Long", e)

103

}

104

105

/**

106

* Get required configuration value as Boolean

107

*/

108

fun ApplicationConfigValue.getBooleanOrFail(): Boolean = try {

109

getString().toBoolean()

110

} catch (e: Exception) {

111

throw ConfigurationException("Cannot convert configuration value to Boolean", e)

112

}

113

```

114

115

### Configuration Implementations

116

117

Concrete implementations of ApplicationConfig for different configuration sources and patterns.

118

119

```kotlin { .api }

120

/**

121

* Map-based implementation of ApplicationConfig

122

*/

123

class MapApplicationConfig : ApplicationConfig {

124

/** Create config from map */

125

constructor(map: Map<String, Any>)

126

/** Create config from vararg pairs */

127

constructor(vararg values: Pair<String, Any>)

128

129

/** Put configuration value */

130

fun put(path: String, value: String)

131

/** Put all values from map */

132

fun putAll(values: Map<String, Any>)

133

/** Remove configuration value */

134

fun remove(path: String)

135

/** Clear all configuration */

136

fun clear()

137

}

138

139

/**

140

* Merges multiple configuration sources with precedence

141

*/

142

class MergedApplicationConfig(vararg sources: ApplicationConfig) : ApplicationConfig {

143

/** Add configuration source with higher precedence */

144

fun withFallback(config: ApplicationConfig): MergedApplicationConfig

145

}

146

147

/**

148

* Empty configuration implementation

149

*/

150

object EmptyApplicationConfig : ApplicationConfig

151

```

152

153

### Configuration Loading

154

155

Utilities for loading configuration from various sources including files, environment variables, and system properties.

156

157

```kotlin { .api }

158

/**

159

* Load configuration from HOCON file

160

* @param file - Configuration file to load

161

* @return ApplicationConfig instance

162

*/

163

fun loadApplicationConfig(file: File): ApplicationConfig

164

165

/**

166

* Load configuration from resource

167

* @param resource - Resource path to load

168

* @return ApplicationConfig instance

169

*/

170

fun loadApplicationConfig(resource: String): ApplicationConfig

171

172

/**

173

* Load configuration from multiple sources

174

* @param sources - Configuration sources in priority order

175

* @return Merged configuration

176

*/

177

fun loadApplicationConfig(vararg sources: ApplicationConfig): ApplicationConfig

178

179

/**

180

* Create configuration from environment variables

181

* @param prefix - Environment variable prefix to filter

182

* @return Configuration from environment

183

*/

184

fun environmentConfig(prefix: String = ""): ApplicationConfig

185

186

/**

187

* Create configuration from system properties

188

* @param prefix - System property prefix to filter

189

* @return Configuration from system properties

190

*/

191

fun systemPropertiesConfig(prefix: String = ""): ApplicationConfig

192

```

193

194

### Configuration Validation

195

196

Utilities for validating configuration values and providing meaningful error messages.

197

198

```kotlin { .api }

199

/**

200

* Configuration validation exception

201

*/

202

class ConfigurationException(message: String, cause: Throwable? = null) : Exception(message, cause)

203

204

/**

205

* Validate configuration property exists

206

* @param path - Configuration path to check

207

* @throws ConfigurationException if property not found

208

*/

209

fun ApplicationConfig.requireProperty(path: String): ApplicationConfigValue {

210

return propertyOrNull(path) ?: throw ConfigurationException("Required configuration property '$path' not found")

211

}

212

213

/**

214

* Validate configuration section exists

215

* @param path - Configuration section path to check

216

* @throws ConfigurationException if section not found

217

*/

218

fun ApplicationConfig.requireConfig(path: String): ApplicationConfig {

219

return try {

220

config(path)

221

} catch (e: Exception) {

222

throw ConfigurationException("Required configuration section '$path' not found", e)

223

}

224

}

225

226

/**

227

* Validate configuration value is in allowed set

228

* @param allowedValues - Set of allowed values

229

* @throws ConfigurationException if value not in set

230

*/

231

fun ApplicationConfigValue.requireOneOf(vararg allowedValues: String): String {

232

val value = getString()

233

if (value !in allowedValues) {

234

throw ConfigurationException("Configuration value '$value' must be one of: ${allowedValues.joinToString()}")

235

}

236

return value

237

}

238

```

239

240

### Configuration Scopes

241

242

Scoped configuration access for different parts of the application with inheritance and overrides.

243

244

```kotlin { .api }

245

/**

246

* Scoped configuration access

247

*/

248

class ConfigurationScope(

249

private val config: ApplicationConfig,

250

private val path: String = ""

251

) {

252

/** Get property in current scope */

253

fun property(name: String): ApplicationConfigValue = config.property(scopedPath(name))

254

/** Get optional property in current scope */

255

fun propertyOrNull(name: String): ApplicationConfigValue? = config.propertyOrNull(scopedPath(name))

256

/** Create nested scope */

257

fun scope(name: String): ConfigurationScope = ConfigurationScope(config, scopedPath(name))

258

259

private fun scopedPath(name: String) = if (path.isEmpty()) name else "$path.$name"

260

}

261

262

/**

263

* Create configuration scope for specific section

264

* @param path - Section path for scope

265

* @return Scoped configuration access

266

*/

267

fun ApplicationConfig.scope(path: String): ConfigurationScope = ConfigurationScope(this, path)

268

```

269

270

**Usage Examples:**

271

272

```kotlin

273

import io.ktor.server.application.*

274

import io.ktor.server.config.*

275

import io.ktor.server.response.*

276

import io.ktor.server.routing.*

277

278

// Basic configuration access

279

fun Application.basicConfigExample() {

280

// Access configuration values

281

val appName = environment.config.property("app.name").getString()

282

val port = environment.config.property("server.port").getInt(8080)

283

val debugMode = environment.config.propertyOrNull("app.debug")?.getBoolean() ?: false

284

285

log.info("Starting $appName on port $port (debug: $debugMode)")

286

287

routing {

288

get("/config") {

289

call.respondText("App: $appName, Port: $port, Debug: $debugMode")

290

}

291

}

292

}

293

294

// Configuration with validation

295

fun Application.validatedConfigExample() {

296

try {

297

// Required configuration

298

val dbUrl = environment.config.requireProperty("database.url").getString()

299

val dbDriver = environment.config.requireProperty("database.driver").getString()

300

301

// Optional with defaults

302

val connectionTimeout = environment.config.propertyOrNull("database.timeout")?.getInt() ?: 30

303

val maxConnections = environment.config.propertyOrNull("database.maxConnections")?.getInt() ?: 10

304

305

// Validated enums

306

val logLevel = environment.config.requireProperty("logging.level")

307

.requireOneOf("DEBUG", "INFO", "WARN", "ERROR")

308

309

log.info("Database: $dbUrl (timeout: ${connectionTimeout}s, max connections: $maxConnections)")

310

log.info("Log level: $logLevel")

311

312

} catch (e: ConfigurationException) {

313

log.error("Configuration error: ${e.message}")

314

throw e

315

}

316

}

317

318

// Nested configuration sections

319

fun Application.nestedConfigExample() {

320

// Database configuration section

321

val dbConfig = environment.config.config("database")

322

val dbUrl = dbConfig.property("url").getString()

323

val dbUser = dbConfig.property("user").getString()

324

val dbPassword = dbConfig.property("password").getString()

325

326

// Server configuration list

327

val serverConfigs = environment.config.configList("servers")

328

for ((index, serverConfig) in serverConfigs.withIndex()) {

329

val host = serverConfig.property("host").getString()

330

val port = serverConfig.property("port").getInt()

331

log.info("Server $index: $host:$port")

332

}

333

334

routing {

335

get("/servers") {

336

val servers = serverConfigs.map { server ->

337

mapOf(

338

"host" to server.property("host").getString(),

339

"port" to server.property("port").getInt()

340

)

341

}

342

call.respond(servers)

343

}

344

}

345

}

346

347

// Programmatic configuration

348

fun Application.programmaticConfigExample() {

349

// Create configuration from map

350

val appConfig = MapApplicationConfig(

351

"app.name" to "My Ktor App",

352

"app.version" to "1.0.0",

353

"server.host" to "localhost",

354

"server.port" to "8080"

355

)

356

357

// Merge with environment variables

358

val envConfig = environmentConfig("KTOR_")

359

val mergedConfig = MergedApplicationConfig(envConfig, appConfig)

360

361

// Access merged configuration

362

val appName = mergedConfig.property("app.name").getString()

363

val host = mergedConfig.property("server.host").getString()

364

val port = mergedConfig.property("server.port").getInt()

365

366

log.info("App: $appName running on $host:$port")

367

}

368

369

// Configuration scopes

370

fun Application.scopedConfigExample() {

371

// Create database scope

372

val dbScope = environment.config.scope("database")

373

val url = dbScope.property("url").getString()

374

val user = dbScope.property("user").getString()

375

376

// Create cache scope

377

val cacheScope = environment.config.scope("cache")

378

val cacheSize = cacheScope.property("size").getInt(1000)

379

val cacheTtl = cacheScope.property("ttl").getLong(3600)

380

381

// Nested scopes

382

val redisScope = cacheScope.scope("redis")

383

val redisHost = redisScope.property("host").getString()

384

val redisPort = redisScope.property("port").getInt(6379)

385

386

log.info("Database: $url (user: $user)")

387

log.info("Cache: size=$cacheSize, ttl=${cacheTtl}s")

388

log.info("Redis: $redisHost:$redisPort")

389

}

390

391

// Route-specific configuration access

392

fun Application.routeConfigExample() {

393

routing {

394

get("/admin") {

395

// Access configuration within route

396

val adminEnabled = call.config.propertyOrNull("admin.enabled")?.getBoolean() ?: false

397

if (!adminEnabled) {

398

call.respond(HttpStatusCode.NotFound)

399

return@get

400

}

401

402

val adminTitle = call.config.property("admin.title").getString()

403

call.respondText("Welcome to $adminTitle")

404

}

405

406

get("/api/limits") {

407

val rateLimit = call.config.property("api.rateLimit").getInt(100)

408

val maxPayload = call.config.property("api.maxPayloadSize").getLong(1024 * 1024)

409

410

call.respond(mapOf(

411

"rateLimit" to rateLimit,

412

"maxPayloadSize" to maxPayload

413

))

414

}

415

}

416

}

417

```

418

419

**Example Configuration File (application.conf):**

420

421

```hocon

422

app {

423

name = "My Ktor Application"

424

version = "1.0.0"

425

debug = false

426

}

427

428

server {

429

host = "0.0.0.0"

430

port = 8080

431

}

432

433

database {

434

url = "jdbc:postgresql://localhost:5432/myapp"

435

driver = "org.postgresql.Driver"

436

user = "appuser"

437

password = "secret"

438

timeout = 30

439

maxConnections = 20

440

}

441

442

cache {

443

size = 10000

444

ttl = 3600

445

redis {

446

host = "localhost"

447

port = 6379

448

}

449

}

450

451

logging {

452

level = "INFO"

453

}

454

455

servers = [

456

{

457

host = "server1.example.com"

458

port = 8080

459

},

460

{

461

host = "server2.example.com"

462

port = 8080

463

}

464

]

465

466

admin {

467

enabled = true

468

title = "Admin Panel"

469

}

470

471

api {

472

rateLimit = 1000

473

maxPayloadSize = 5242880 # 5MB

474

}

475

```