Skip to content

Commit a6d91b8

Browse files
committed
KTOR-8602 Fix handling of optional module parameters
1 parent 3ad8f19 commit a6d91b8

File tree

2 files changed

+45
-21
lines changed

2 files changed

+45
-21
lines changed

ktor-server/ktor-server-core/jvm/src/io/ktor/server/engine/internal/CallableUtils.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,23 +107,23 @@ private suspend fun <R> callFunctionWithInjection(
107107
parameter.kind == KParameter.Kind.INSTANCE -> instance
108108
isApplicationEnvironment(parameter) -> application.environment
109109
isApplication(parameter) -> application
110-
parameter.type.toString().contains("Application") -> {
111-
// It is possible that type is okay, but classloader is not
112-
val classLoader = (parameter.type.javaType as? Class<*>)?.classLoader
113-
throw IllegalArgumentException(
114-
"Parameter type ${parameter.type}:{$classLoader} is not supported." +
115-
"Application is loaded as " +
116-
"$ApplicationClassInstance:{${ApplicationClassInstance.classLoader}}"
117-
)
118-
}
110+
119111
else -> {
120-
val injectedValue = runCatching {
121-
moduleInjector.resolveParameter(application, parameter)
122-
}
112+
val injectedValue = runCatching { moduleInjector.resolveParameter(application, parameter) }
123113
when {
124114
injectedValue.isSuccess -> injectedValue.getOrThrow()
125115
parameter.isOptional -> return@mapNotNull null // skip
126116
parameter.type.isMarkedNullable -> null // value = null
117+
// This check should go last
118+
parameter.type.toString().contains("Application") -> {
119+
// It is possible that type is okay, but classloader is not
120+
val classLoader = (parameter.type.javaType as? Class<*>)?.classLoader
121+
throw IllegalArgumentException(
122+
"Parameter type ${parameter.type}:{$classLoader} is not supported. " +
123+
"Application is loaded as " +
124+
"$ApplicationClassInstance:{${ApplicationClassInstance.classLoader}}"
125+
)
126+
}
127127
else -> throw IllegalArgumentException(
128128
"Failed to inject parameter `${parameter.name ?: "<receiver>"}: ${parameter.type}` " +
129129
"in module function `$entryPoint`",

ktor-server/ktor-server-core/jvm/test/io/ktor/tests/hosts/EmbeddedServerReloadingTests.kt

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
package io.ktor.tests.hosts
88

9-
import com.typesafe.config.*
9+
import com.typesafe.config.ConfigFactory
1010
import io.ktor.client.request.*
1111
import io.ktor.events.*
1212
import io.ktor.server.application.*
@@ -15,11 +15,16 @@ import io.ktor.server.engine.*
1515
import io.ktor.server.response.*
1616
import io.ktor.server.routing.*
1717
import io.ktor.server.testing.*
18+
import io.ktor.tests.hosts.EmbeddedServerReloadingTests.Companion.addLoadedModule
1819
import io.ktor.util.*
19-
import kotlinx.coroutines.*
20-
import org.slf4j.helpers.*
21-
import kotlin.reflect.*
22-
import kotlin.reflect.jvm.*
20+
import kotlinx.coroutines.Job
21+
import kotlinx.coroutines.runBlocking
22+
import org.slf4j.helpers.NOPLogger
23+
import kotlin.reflect.KClass
24+
import kotlin.reflect.KFunction
25+
import kotlin.reflect.KFunction0
26+
import kotlin.reflect.jvm.javaMethod
27+
import kotlin.reflect.jvm.jvmName
2328
import kotlin.test.*
2429

2530
class EmbeddedServerReloadingTests {
@@ -391,7 +396,8 @@ class EmbeddedServerReloadingTests {
391396
mapOf(
392397
"ktor.deployment.environment" to "test",
393398
"ktor.application.modules" to listOf(
394-
EmbeddedServerReloadingTests::class.jvmName + "Kt.topLevelWithDefaultArg"
399+
Application::defaultArgBoolean.fqName,
400+
Application::defaultArgContainingApplicationWord.fqName,
395401
)
396402
)
397403
)
@@ -405,7 +411,13 @@ class EmbeddedServerReloadingTests {
405411
server.start()
406412
val application = server.application
407413
assertNotNull(application)
408-
assertEquals("topLevelWithDefaultArg", application.attributes[TestKey])
414+
assertEquals(
415+
setOf(
416+
"defaultArgBoolean",
417+
"defaultArgContainingApplicationWord",
418+
),
419+
application.loadedModules,
420+
)
409421
server.stop()
410422
}
411423

@@ -512,6 +524,14 @@ class EmbeddedServerReloadingTests {
512524
companion object {
513525
val TestKey = AttributeKey<String>("test-key")
514526
val TestKey2 = AttributeKey<String>("test-key2")
527+
private val LoadedModulesKey = AttributeKey<MutableSet<String>>("loaded-modules")
528+
529+
val Application.loadedModules: Set<String>
530+
get() = attributes.getOrNull(LoadedModulesKey).orEmpty()
531+
532+
fun Application.addLoadedModule(name: String) {
533+
attributes.computeIfAbsent(LoadedModulesKey) { mutableSetOf() }.add(name)
534+
}
515535

516536
private val KFunction<*>.fqName: String
517537
get() = javaMethod!!.declaringClass.name + "." + name
@@ -652,8 +672,12 @@ fun topLevelFunction() {
652672
error("Shouldn't be invoked")
653673
}
654674

655-
fun Application.topLevelWithDefaultArg(testing: Boolean = false) {
656-
attributes.put(EmbeddedServerReloadingTests.TestKey, "topLevelWithDefaultArg")
675+
fun Application.defaultArgBoolean(testing: Boolean = false) {
676+
addLoadedModule("defaultArgBoolean")
677+
}
678+
679+
fun Application.defaultArgContainingApplicationWord(configure: Application.() -> Unit = {}) {
680+
addLoadedModule("defaultArgContainingApplicationWord")
657681
}
658682

659683
@JvmOverloads

0 commit comments

Comments
 (0)