or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdconfiguration.mdengine.mdindex.mdrequest-response.mdrouting.md

application.mddocs/

0

# Application Management

1

2

Ktor's application management system provides comprehensive lifecycle control, plugin architecture, and event handling for web applications. The Application class serves as the central coordinator for all server functionality.

3

4

## Core Application Class

5

6

### Application Class

7

8

```kotlin { .api }

9

class Application internal constructor(

10

environment: ApplicationEnvironment,

11

developmentMode: Boolean,

12

rootPath: String,

13

monitor: Events,

14

parentCoroutineContext: CoroutineContext,

15

engineProvider: () -> ApplicationEngine

16

) : ApplicationCallPipeline, CoroutineScope {

17

val engine: ApplicationEngine

18

var rootPath: String

19

val monitor: Events

20

val parentCoroutineContext: CoroutineContext

21

22

suspend fun disposeAndJoin()

23

}

24

```

25

26

### Application Properties

27

28

```kotlin { .api }

29

// Access application properties

30

val app: Application = /* ... */

31

32

// Engine that runs the application (may be null during testing)

33

val engine: ApplicationEngine? = app.engine

34

35

// Root path for the application (useful for sub-applications)

36

val rootPath: String = app.rootPath

37

38

// Event monitoring system

39

val monitor: Events = app.monitor

40

41

// Parent coroutine context for structured concurrency

42

val parentContext: CoroutineContext = app.parentCoroutineContext

43

```

44

45

### Application Lifecycle

46

47

```kotlin { .api }

48

// Dispose application resources

49

val disposeJob: Job = application.dispose()

50

51

// Dispose and wait for completion

52

application.disposeAndJoin()

53

```

54

55

## Application Call Pipeline

56

57

The `ApplicationCallPipeline` processes incoming requests through defined phases.

58

59

### Pipeline Phases

60

61

```kotlin { .api }

62

// Standard pipeline phases

63

object ApplicationPhase {

64

val Setup = PipelinePhase("Setup")

65

val Monitoring = PipelinePhase("Monitoring")

66

val Plugins = PipelinePhase("Plugins")

67

val Call = PipelinePhase("Call")

68

val Fallback = PipelinePhase("Fallback")

69

}

70

```

71

72

### Pipeline Configuration

73

74

```kotlin { .api }

75

class ApplicationCallPipeline(

76

developmentMode: Boolean = false,

77

environment: ApplicationEnvironment

78

) {

79

val receivePipeline: ApplicationReceivePipeline

80

val sendPipeline: ApplicationSendPipeline

81

val developmentMode: Boolean

82

val environment: ApplicationEnvironment

83

}

84

```

85

86

## Application Call Interface

87

88

### ApplicationCall Properties

89

90

```kotlin { .api }

91

interface ApplicationCall : CoroutineScope {

92

val attributes: Attributes

93

val request: ApplicationRequest

94

val response: ApplicationResponse

95

val application: Application

96

val parameters: Parameters

97

98

suspend fun <T> receiveNullable(typeInfo: TypeInfo): T?

99

suspend fun respond(message: Any?, typeInfo: TypeInfo?)

100

}

101

102

interface PipelineCall : ApplicationCall {

103

override val request: PipelineRequest

104

override val response: PipelineResponse

105

}

106

```

107

108

### Pipeline Call Implementation

109

110

```kotlin { .api }

111

interface PipelineCall : ApplicationCall {

112

val request: PipelineRequest

113

val response: PipelineResponse

114

}

115

```

116

117

### Context Extensions

118

119

```kotlin { .api }

120

// Access current call from pipeline context

121

val PipelineContext<*, PipelineCall>.call: PipelineCall

122

123

// Access current application from pipeline context

124

val PipelineContext<*, PipelineCall>.application: Application

125

```

126

127

## Plugin System

128

129

### Plugin Interface

130

131

```kotlin { .api }

132

interface Plugin<TPipeline : Any, TConfiguration : Any, TPlugin : Any> {

133

val key: AttributeKey<TPlugin>

134

fun install(pipeline: TPipeline, configure: TConfiguration.() -> Unit): TPlugin

135

}

136

```

137

138

### Application Plugin Types

139

140

```kotlin { .api }

141

// Base application plugin interface

142

interface BaseApplicationPlugin<TPipeline : Any, TConfiguration : Any, TPlugin : Any> :

143

Plugin<TPipeline, TConfiguration, TPlugin>

144

145

// Simplified application plugin interface

146

interface ApplicationPlugin<TConfiguration : Any> :

147

BaseApplicationPlugin<Application, TConfiguration, *>

148

```

149

150

### Plugin Installation

151

152

```kotlin { .api }

153

// Install plugin with configuration

154

fun <P : Pipeline<*, ApplicationCall>, B : Any, F : Any> P.install(

155

plugin: Plugin<P, B, F>,

156

configure: B.() -> Unit = {}

157

): F

158

159

// Example plugin installation

160

fun Application.configurePlugins() {

161

install(ContentNegotiation) {

162

json {

163

prettyPrint = true

164

isLenient = true

165

}

166

}

167

168

install(CallLogging) {

169

level = Level.INFO

170

filter { call -> call.request.path().startsWith("/api/") }

171

}

172

}

173

```

174

175

### Plugin Access

176

177

```kotlin { .api }

178

// Get installed plugin instance (throws if not installed)

179

fun <F : Any> ApplicationCallPipeline.plugin(key: AttributeKey<F>): F

180

181

// Get plugin instance or null

182

fun <F : Any> ApplicationCallPipeline.pluginOrNull(key: AttributeKey<F>): F?

183

184

// Access plugin registry

185

val ApplicationCallPipeline.pluginRegistry: PluginRegistry

186

187

// Example plugin access

188

fun Application.usePlugin() {

189

val contentNegotiation = plugin(ContentNegotiation)

190

val logging = pluginOrNull(CallLogging)

191

192

if (logging != null) {

193

// Plugin is installed, use it

194

}

195

}

196

```

197

198

### Plugin Creation

199

200

```kotlin { .api }

201

// Create application plugin with configuration

202

fun <TConfiguration : Any> createApplicationPlugin(

203

name: String,

204

createConfiguration: () -> TConfiguration,

205

body: PluginBuilder<TConfiguration>.() -> Unit

206

): ApplicationPlugin<TConfiguration>

207

208

// Create route-scoped plugin

209

fun <TConfiguration : Any> createRouteScopedPlugin(

210

name: String,

211

createConfiguration: () -> TConfiguration,

212

body: PluginBuilder<TConfiguration>.() -> Unit

213

): Plugin<Route, TConfiguration, Unit>

214

215

// Example custom plugin

216

val CustomPlugin = createApplicationPlugin("CustomPlugin", ::CustomConfig) {

217

val config = pluginConfig

218

219

onCall { call ->

220

// Plugin logic for each call

221

call.attributes.put(CustomAttributeKey, config.value)

222

}

223

224

onCallReceive { call ->

225

// Intercept request content

226

transformBody { data ->

227

// Transform incoming data

228

processData(data)

229

}

230

}

231

}

232

233

// Plugin configuration class

234

class CustomConfig {

235

var value: String = "default"

236

var enabled: Boolean = true

237

}

238

```

239

240

## Exception Handling

241

242

### Plugin Exceptions

243

244

```kotlin { .api }

245

// Thrown when attempting to install duplicate plugin

246

class DuplicatePluginException(key: String) : Exception(

247

"Plugin $key is already installed"

248

)

249

250

// Thrown when accessing non-installed plugin

251

class MissingApplicationPluginException(key: AttributeKey<*>) : Exception(

252

"Plugin ${key.name} has not been installed"

253

)

254

```

255

256

### Exception Usage

257

258

```kotlin { .api }

259

fun Application.handlePluginErrors() {

260

try {

261

install(SomePlugin)

262

install(SomePlugin) // This will throw DuplicatePluginException

263

} catch (e: DuplicatePluginException) {

264

log.warn("Plugin already installed: ${e.message}")

265

}

266

267

try {

268

val plugin = plugin(NonInstalledPlugin.key)

269

} catch (e: MissingApplicationPluginException) {

270

log.error("Required plugin not installed: ${e.message}")

271

}

272

}

273

```

274

275

## Event System

276

277

### Application Events

278

279

```kotlin { .api }

280

// Application lifecycle events

281

object ApplicationStarting : EventDefinition<Application>()

282

object ApplicationModulesLoading : EventDefinition<Application>()

283

object ApplicationModulesLoaded : EventDefinition<Application>()

284

object ApplicationStarted : EventDefinition<Application>()

285

object ServerReady : EventDefinition<ApplicationEngine>()

286

object ApplicationStopPreparing : EventDefinition<Application>()

287

object ApplicationStopping : EventDefinition<Application>()

288

object ApplicationStopped : EventDefinition<Application>()

289

```

290

291

### Event Subscription

292

293

```kotlin { .api }

294

fun Application.subscribeToEvents() {

295

// Subscribe to application start

296

monitor.subscribe(ApplicationStarted) { application ->

297

application.log.info("Application started successfully")

298

// Initialize resources, open connections, etc.

299

}

300

301

// Subscribe to server ready (engine-specific)

302

monitor.subscribe(ServerReady) { engine ->

303

val connectors = engine.resolvedConnectors()

304

log.info("Server ready on connectors: $connectors")

305

}

306

307

// Subscribe to application stop preparation

308

monitor.subscribe(ApplicationStopPreparing) { application ->

309

application.log.info("Preparing to stop application")

310

// Clean up resources, close connections, etc.

311

}

312

313

// Subscribe to application stopped

314

monitor.subscribe(ApplicationStopped) { application ->

315

application.log.info("Application stopped")

316

}

317

}

318

```

319

320

### Event Raising

321

322

```kotlin { .api }

323

// Raise custom events

324

fun Application.raiseCustomEvent() {

325

// Define custom event

326

object CustomEvent : EventDefinition<String>()

327

328

// Subscribe to custom event

329

monitor.subscribe(CustomEvent) { data ->

330

log.info("Custom event received: $data")

331

}

332

333

// Raise the event

334

monitor.raise(CustomEvent, "event data")

335

}

336

```

337

338

## Hook System

339

340

### Hook Interface

341

342

```kotlin { .api }

343

interface Hook<HookHandler : Function<Unit>> {

344

fun install(pipeline: ApplicationCallPipeline, handler: HookHandler)

345

}

346

```

347

348

### Using Hooks

349

350

```kotlin { .api }

351

fun Application.setupHooks() {

352

// Example hook usage (implementation depends on specific hooks available)

353

// Hooks provide extension points for plugin developers

354

355

// Install hook handler

356

MyHook.install(this) { context ->

357

// Hook implementation

358

log.debug("Hook executed for call: ${context.call.request.uri}")

359

}

360

}

361

```

362

363

## Server Configuration

364

365

### ServerConfig Class

366

367

```kotlin { .api }

368

data class ServerConfig internal constructor(

369

val environment: ApplicationEnvironment,

370

val rootPath: String = "",

371

val developmentMode: Boolean = false,

372

val parentCoroutineContext: CoroutineContext? = null

373

) {

374

// Internal properties

375

internal val modules: List<Application.() -> Unit>

376

internal val watchPaths: List<String>

377

}

378

```

379

380

### ServerConfigBuilder

381

382

```kotlin { .api }

383

class ServerConfigBuilder {

384

var environment: ApplicationEnvironment

385

var watchPaths: MutableList<String>

386

var rootPath: String = ""

387

var developmentMode: Boolean = false

388

var parentCoroutineContext: CoroutineContext? = null

389

390

// Install application module

391

fun module(body: Application.() -> Unit)

392

}

393

```

394

395

### Server Configuration Creation

396

397

```kotlin { .api }

398

// Create server configuration

399

fun serverConfig(

400

configure: ServerConfigBuilder.() -> Unit = {}

401

): ServerConfig

402

403

// Example server configuration

404

val config = serverConfig {

405

environment = applicationEnvironment {

406

// Environment configuration

407

}

408

409

developmentMode = true

410

rootPath = "/api"

411

412

module {

413

// Application module configuration

414

configureRouting()

415

configureSerialization()

416

}

417

418

module {

419

// Additional module

420

configureSecurity()

421

}

422

}

423

```

424

425

## Logging

426

427

### Application Logging

428

429

```kotlin { .api }

430

// Access logger from Application

431

val Application.log: Logger

432

433

// Example logging usage

434

fun Application.configureLogging() {

435

log.info("Configuring application")

436

437

monitor.subscribe(ApplicationStarted) { app ->

438

app.log.info("Application started successfully")

439

}

440

441

monitor.subscribe(ApplicationStopPreparing) { app ->

442

app.log.warn("Application is preparing to stop")

443

}

444

}

445

```

446

447

### MDC Provider

448

449

```kotlin { .api }

450

// MDC (Mapped Diagnostic Context) for structured logging

451

interface MDCProvider {

452

fun withMDCBlock(block: () -> Unit)

453

}

454

```

455

456

## Complete Application Example

457

458

```kotlin { .api }

459

fun main() {

460

val server = embeddedServer(Netty, port = 8080) {

461

// Install core plugins

462

install(ContentNegotiation) {

463

json()

464

}

465

466

install(CallLogging) {

467

level = Level.INFO

468

}

469

470

// Subscribe to application events

471

monitor.subscribe(ApplicationStarted) { app ->

472

app.log.info("Server started on port 8080")

473

}

474

475

// Configure routing

476

routing {

477

get("/") {

478

call.respondText("Hello, Ktor!")

479

}

480

481

get("/plugins") {

482

val plugins = pluginRegistry.allKeys.map { it.name }

483

call.respond(plugins)

484

}

485

}

486

487

// Custom plugin installation

488

install(createApplicationPlugin("RequestId") {

489

onCall { call ->

490

val requestId = UUID.randomUUID().toString()

491

call.attributes.put(RequestIdKey, requestId)

492

call.response.header("X-Request-ID", requestId)

493

}

494

})

495

}

496

497

server.start(wait = true)

498

}

499

500

val RequestIdKey = AttributeKey<String>("RequestId")

501

```

502

503

This comprehensive documentation covers all aspects of Ktor's application management system, from basic lifecycle control to advanced plugin development and event handling.