Closed SerVB closed 4 years ago
And if I change jackson to gson, I can't even run my app:
The issue is that there is a map type that apparently has no map types... I didn't think this could happen...
can you provide sample code that does this error ?
Oh, Right... Do you have a class that extends the Map<K, V>
Interface ?
can you provide sample code that does this error ?
Sure.
This is the revision: https://github.com/SerVB/e-shop/tree/4db3eda7e80a3e249d2254b3bd190c3c03df3cce .
Sometimes when running ./gradlew check
all tests fail (in normal case some of them pass 😀 – I'm doing TDD and haven't implemented everything yet).
If you want 100% fail (as in the second stacktrace), please apply this patch:
Index: server/src/main/kotlin/io/github/servb/eShop/Application.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- server/src/main/kotlin/io/github/servb/eShop/Application.kt (revision 4db3eda7e80a3e249d2254b3bd190c3c03df3cce)
+++ server/src/main/kotlin/io/github/servb/eShop/Application.kt (date 1585348344348)
@@ -18,7 +18,7 @@
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.features.ContentNegotiation
-import io.ktor.jackson.jackson
+import io.ktor.gson.gson
import io.ktor.response.respond
import io.ktor.response.respondRedirect
import io.ktor.routing.get
@@ -57,7 +57,7 @@
}
install(ContentNegotiation) {
- jackson()
+ gson()
}
install(OpenAPIGen) {
Index: server/build.gradle.kts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- server/build.gradle.kts (revision 4db3eda7e80a3e249d2254b3bd190c3c03df3cce)
+++ server/build.gradle.kts (date 1585347374395)
@@ -52,7 +52,7 @@
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
implementation("io.ktor:ktor-server-core:$ktorVersion")
- implementation("io.ktor:ktor-jackson:$ktorVersion")
+ implementation("io.ktor:ktor-gson:$ktorVersion")
implementation("com.github.papsign:Ktor-OpenAPI-Generator:$ktorOpenApiGeneratorVersion")
implementation("org.jetbrains.exposed:exposed-core:$exposedVersion")
implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion")
Then running with set env io.github.servb.eShop.forceInMemory=true
./gradlew run
should fail.
Do you have a class that extends the Map<K, V> Interface ?
No...
By the way, if I do gson { serializeNulls() }
, it doesn't fail.
The issue still blinks. I have about 50% of launches failing (do you have any idea why not always?). I've just done a small investigation: I've put a breakpoint at the failing place:
The problematic type is Nothing?
: it doesn't have arguments:
I have such an object in my code:
interface OptionalResult<out ResultType : Any> {
val data: ResultType?
object FAIL : OptionalResult<Nothing> {
override val data = null
}
}
I use it as an example in throws
block in some places like this:
throws(
status = HttpStatusCode.NotFound.description("The product does not exist."),
example = OptionalResult.FAIL,
exClass = IllegalArgumentException::class
) { ... }
Does it help?
That is it... it is odd that nothing is matched to a map type... I use the kotlin reflection isSubType
function. Remove all the Nothings and use Unit
instead, it should work.
Oh, I think I've hacked it!
Nothing?
type is a subtype of any nullable type so it's mapped to the first map entry:
And tests blink because an order in the map can be random so sometimes it goes like this (which gives passing tests):
And sometimes like this (which gives failing tests):
I don't know exactly how SchemaProvider
is working but it seems that there are many types defined and some strategies for them too. Maybe Nothing?
can be added somewhere?
Remove all the Nothings and use
Unit
instead, it should work.
Sorry, I don't want to do this... For me it's very vital to have an opportunity to use OptionalResult.FAIL
as all types like OptionalResult<String>
or OptionalResult<MyDataClass>
. If I change Nothing?
to Unit?
, it simply won't work because Unit
isn't a subtype of any type – it's only a subtype of Any
.
The SchemaProvider works by using a Treeset with a comparator on IsSubtype. Registering a SchemaProvider for Nothing
should solve this, as it will be a subtype of everything, thus handled first.
I have pushed the appropriate modifications to the reworked-model
branch, it should work in theory.
Tell me if it properly works now, i will make a pre-release and close the issue.
It works.
Sometimes when I run tests, I get the following exception for all tests:
Stacktrace
``` java.lang.IndexOutOfBoundsException: Empty list doesn't contain element at index 0. at kotlin.collections.EmptyList.get(Collections.kt:35) at kotlin.collections.EmptyList.get(Collections.kt:23) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultMapSchemaProvider$Builder.build(DefaultMapSchemaProvider.kt:22) at com.papsign.ktor.openapigen.schema.builder.provider.FinalSchemaBuilderProvider$Builder.build(FinalSchemaBuilderProvider.kt:70) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultObjectSchemaProvider$Builder$build$1.invoke(DefaultObjectSchemaProvider.kt:50) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultObjectSchemaProvider$Builder$build$1.invoke(DefaultObjectSchemaProvider.kt:30) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultObjectSchemaProvider$Builder.build(DefaultObjectSchemaProvider.kt:39) at com.papsign.ktor.openapigen.schema.builder.provider.FinalSchemaBuilderProvider$Builder.build(FinalSchemaBuilderProvider.kt:70) at com.papsign.ktor.openapigen.schema.builder.FinalSchemaBuilder$DefaultImpls.build$default(FinalSchemaBuilder.kt:8) at com.papsign.ktor.openapigen.content.type.ktor.KtorContentProvider.getMediaType(KtorContentProvider.kt:63) at com.papsign.ktor.openapigen.modules.handlers.ThrowOperationHandler.configure(ThrowOperationHandler.kt:27) at com.papsign.ktor.openapigen.modules.handlers.RouteHandler.configure(RouteHandler.kt:32) at io.github.servb.eShop.handler.product.v1.CreateProductKt.createProduct(createProduct.kt:169) at io.github.servb.eShop.route.product.v1.AddProductV1RoutesKt.addProductV1Routes(addProductV1Routes.kt:7) at io.github.servb.eShop.ApplicationKt$module$4.invoke(Application.kt:106) at io.github.servb.eShop.ApplicationKt$module$4.invoke(Application.kt) at com.papsign.ktor.openapigen.route.RouteConfigKt$apiRouting$1.invoke(RouteConfig.kt:17) at com.papsign.ktor.openapigen.route.RouteConfigKt$apiRouting$1.invoke(RouteConfig.kt) at io.ktor.routing.RoutingKt.routing(Routing.kt:120) at com.papsign.ktor.openapigen.route.RouteConfigKt.apiRouting(RouteConfig.kt:13) at io.github.servb.eShop.ApplicationKt.module(Application.kt:89) at io.github.servb.eShop.product.InMemoryEShopProductKt.inMemoryEShopProduct(inMemoryEShopProduct.kt:6) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1$1.invoke(EShopProductCreateProductTest.kt:20) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1$1.invoke(EShopProductCreateProductTest.kt:18) at io.ktor.server.testing.TestEngineKt$withTestApplication$1.invoke(TestEngine.kt:67) at io.ktor.server.testing.TestEngineKt$withTestApplication$1.invoke(TestEngine.kt) at io.ktor.server.testing.TestEngineKt.withApplication(TestEngine.kt:49) at io.ktor.server.testing.TestEngineKt.withApplication$default(TestEngine.kt:43) at io.ktor.server.testing.TestEngineKt.withTestApplication(TestEngine.kt:66) at io.github.servb.eShop.util.KotlinFutureKt.withTestApplication(KotlinFuture.kt:13) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1.invokeSuspend(EShopProductCreateProductTest.kt:20) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1.invoke(EShopProductCreateProductTest.kt) at io.kotest.core.spec.style.BehaviorSpecDsl$addGivenContext$1.invokeSuspend(behaviorSpecDsl.kt:25) at io.kotest.core.spec.style.BehaviorSpecDsl$addGivenContext$1.invoke(behaviorSpecDsl.kt) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2$1.invokeSuspend(executions.kt:16) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2$1.invoke(executions.kt) at io.kotest.core.AsserterKt.executeWithGlobalAssertSoftlyCheck(Asserter.kt:37) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2.invokeSuspend(executions.kt:16) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2.invoke(executions.kt) at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102) at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:78) at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:31) at io.kotest.core.runtime.ExecutionsKt.executeWithTimeout--MKxnPQ(executions.kt:13) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1$3.invokeSuspend(TestExecutor.kt:181) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1$3.invoke(TestExecutor.kt) at io.kotest.core.runtime.ReplayKt.replay(replay.kt:19) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1.invokeSuspend(TestExecutor.kt:176) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1.invoke(TestExecutor.kt) at io.kotest.core.runtime.ExecutorExecutionContext$executeWithTimeoutInterruption$$inlined$suspendCoroutine$lambda$2.invokeSuspend(ExecutorExecutionContext.kt:47) (Coroutine boundary) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1$3.invokeSuspend(TestExecutor.kt:181) at io.kotest.core.runtime.ReplayKt.replay(replay.kt:19) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1.invokeSuspend(TestExecutor.kt:180) Caused by: java.lang.IndexOutOfBoundsException: Empty list doesn't contain element at index 0. at kotlin.collections.EmptyList.get(Collections.kt:35) at kotlin.collections.EmptyList.get(Collections.kt:23) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultMapSchemaProvider$Builder.build(DefaultMapSchemaProvider.kt:22) at com.papsign.ktor.openapigen.schema.builder.provider.FinalSchemaBuilderProvider$Builder.build(FinalSchemaBuilderProvider.kt:70) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultObjectSchemaProvider$Builder$build$1.invoke(DefaultObjectSchemaProvider.kt:50) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultObjectSchemaProvider$Builder$build$1.invoke(DefaultObjectSchemaProvider.kt:30) at com.papsign.ktor.openapigen.schema.builder.provider.DefaultObjectSchemaProvider$Builder.build(DefaultObjectSchemaProvider.kt:39) at com.papsign.ktor.openapigen.schema.builder.provider.FinalSchemaBuilderProvider$Builder.build(FinalSchemaBuilderProvider.kt:70) at com.papsign.ktor.openapigen.schema.builder.FinalSchemaBuilder$DefaultImpls.build$default(FinalSchemaBuilder.kt:8) at com.papsign.ktor.openapigen.content.type.ktor.KtorContentProvider.getMediaType(KtorContentProvider.kt:63) at com.papsign.ktor.openapigen.modules.handlers.ThrowOperationHandler.configure(ThrowOperationHandler.kt:27) at com.papsign.ktor.openapigen.modules.handlers.RouteHandler.configure(RouteHandler.kt:32) at io.github.servb.eShop.handler.product.v1.CreateProductKt.createProduct(createProduct.kt:169) at io.github.servb.eShop.route.product.v1.AddProductV1RoutesKt.addProductV1Routes(addProductV1Routes.kt:7) at io.github.servb.eShop.ApplicationKt$module$4.invoke(Application.kt:106) at io.github.servb.eShop.ApplicationKt$module$4.invoke(Application.kt) at com.papsign.ktor.openapigen.route.RouteConfigKt$apiRouting$1.invoke(RouteConfig.kt:17) at com.papsign.ktor.openapigen.route.RouteConfigKt$apiRouting$1.invoke(RouteConfig.kt) at io.ktor.routing.RoutingKt.routing(Routing.kt:120) at com.papsign.ktor.openapigen.route.RouteConfigKt.apiRouting(RouteConfig.kt:13) at io.github.servb.eShop.ApplicationKt.module(Application.kt:89) at io.github.servb.eShop.product.InMemoryEShopProductKt.inMemoryEShopProduct(inMemoryEShopProduct.kt:6) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1$1.invoke(EShopProductCreateProductTest.kt:20) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1$1.invoke(EShopProductCreateProductTest.kt:18) at io.ktor.server.testing.TestEngineKt$withTestApplication$1.invoke(TestEngine.kt:67) at io.ktor.server.testing.TestEngineKt$withTestApplication$1.invoke(TestEngine.kt) at io.ktor.server.testing.TestEngineKt.withApplication(TestEngine.kt:49) at io.ktor.server.testing.TestEngineKt.withApplication$default(TestEngine.kt:43) at io.ktor.server.testing.TestEngineKt.withTestApplication(TestEngine.kt:66) at io.github.servb.eShop.util.KotlinFutureKt.withTestApplication(KotlinFuture.kt:13) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1.invokeSuspend(EShopProductCreateProductTest.kt:20) at io.github.servb.eShop.product.route.singleOperation.EShopProductCreateProductTest$1$1.invoke(EShopProductCreateProductTest.kt) at io.kotest.core.spec.style.BehaviorSpecDsl$addGivenContext$1.invokeSuspend(behaviorSpecDsl.kt:25) at io.kotest.core.spec.style.BehaviorSpecDsl$addGivenContext$1.invoke(behaviorSpecDsl.kt) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2$1.invokeSuspend(executions.kt:16) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2$1.invoke(executions.kt) at io.kotest.core.AsserterKt.executeWithGlobalAssertSoftlyCheck(Asserter.kt:37) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2.invokeSuspend(executions.kt:16) at io.kotest.core.runtime.ExecutionsKt$executeWithTimeout$2.invoke(executions.kt) at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102) at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:78) at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:31) at io.kotest.core.runtime.ExecutionsKt.executeWithTimeout--MKxnPQ(executions.kt:13) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1$3.invokeSuspend(TestExecutor.kt:181) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1$3.invoke(TestExecutor.kt) at io.kotest.core.runtime.ReplayKt.replay(replay.kt:19) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1.invokeSuspend(TestExecutor.kt:176) at io.kotest.core.runtime.TestExecutor$executeAndWait$2$1.invoke(TestExecutor.kt) at io.kotest.core.runtime.ExecutorExecutionContext$executeWithTimeoutInterruption$$inlined$suspendCoroutine$lambda$2.invokeSuspend(ExecutorExecutionContext.kt:47) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56) at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:272) at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79) at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54) at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source) at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36) at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) at io.kotest.core.runtime.ExecutorExecutionContext.executeWithTimeoutInterruption-D5N0EJY(ExecutorExecutionContext.kt:46) at io.kotest.core.runtime.TestExecutor$executeAndWait$2.invokeSuspend(TestExecutor.kt:168) at io.kotest.core.runtime.TestExecutor$executeAndWait$2.invoke(TestExecutor.kt) at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91) at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:177) at io.kotest.core.runtime.TestExecutor.executeAndWait-xkB6VbI(TestExecutor.kt:165) at io.kotest.core.runtime.TestExecutor.invokeTestCase(TestExecutor.kt:149) at io.kotest.core.runtime.TestExecutor.executeActiveTest(TestExecutor.kt:116) at io.kotest.core.runtime.TestExecutor$intercept$2.invokeSuspend(TestExecutor.kt:73) at io.kotest.core.runtime.TestExecutor$intercept$2.invoke(TestExecutor.kt) at io.kotest.core.runtime.TestExecutor.executeIfActive(TestExecutor.kt:85) at io.kotest.core.runtime.TestExecutor.intercept(TestExecutor.kt:73) at io.kotest.core.runtime.TestExecutor.execute(TestExecutor.kt:54) at io.kotest.core.engine.SingleInstanceSpecRunner.runTest(SingleInstanceSpecRunner.kt:63) at io.kotest.core.engine.SingleInstanceSpecRunner$execute$2.invokeSuspend(SingleInstanceSpecRunner.kt:74) at io.kotest.core.engine.SingleInstanceSpecRunner$execute$2.invoke(SingleInstanceSpecRunner.kt) at io.kotest.core.engine.SingleInstanceSpecRunner$execute$3.invokeSuspend(SingleInstanceSpecRunner.kt:80) at io.kotest.core.engine.SingleInstanceSpecRunner$execute$3.invoke(SingleInstanceSpecRunner.kt) at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91) at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:177) at io.kotest.core.engine.SingleInstanceSpecRunner.execute(SingleInstanceSpecRunner.kt:78) at io.kotest.core.engine.SpecExecutor$runTests$run$1.invokeSuspend(SpecExecutor.kt:105) at io.kotest.core.engine.SpecExecutor$runTests$run$1.invoke(SpecExecutor.kt) at io.kotest.core.engine.SpecExecutor.interceptSpec(SpecExecutor.kt:117) at io.kotest.core.engine.SpecExecutor.runTests(SpecExecutor.kt:108) at io.kotest.core.engine.SpecExecutor.execute(SpecExecutor.kt:36) at io.kotest.core.engine.KotestEngine$submitBatch$$inlined$forEach$lambda$1$1.invokeSuspend(KotestEngine.kt:78) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56) at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:272) at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79) at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54) at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source) at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36) at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) at io.kotest.core.engine.KotestEngine$submitBatch$$inlined$forEach$lambda$1.run(KotestEngine.kt:77) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) ```Could you investigate?