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.