FasterXML / jackson-module-kotlin

Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
Apache License 2.0
1.12k stars 175 forks source link

Serialization in Ktor project fails #764

Closed oSumAtrIX closed 8 months ago

oSumAtrIX commented 8 months ago

Your question

About

I am using Jackson inside a library. Jackson seems to work fine in that library and also in applications where I use that library, but in a particular project where I also use Ktor, I can't get Jackson to work. I use jacksonObjectMapper() in the library to serialize an object to JSON but get a stack trace while doing so.

Reproduction

The issue is reproducible with https://github.com/ReVanced/revanced-api/tree/5e86c485be480a7bc74b1792b7dee6484e99785d

The reproduction steps are as follows:

  1. Setup the project according to the README

    Example .env file:

    CONFIG_FILE_PATH=configuration.toml
    
    DB_URL=jdbc:h2:./persistence/revanced-api
    DB_USER=ReVanced
    DB_PASSWORD=ReVanced
    
    JWT_SECRET=ReVanced
    JWT_ISSUER=ReVanced
    JWT_VALIDITY_IN_MIN=5
    
    BASIC_USERNAME=ReVanced
    BASIC_PASSWORD=ReVanced

    Example configuration.toml file:

    organization = "revanced"
    patches-repository = "revanced-patches"
    integrations-repositories = [
        "revanced-integrations"
    ]
    contributors-repositories = [
        "revanced-patcher",
        "revanced-patches",
        "revanced-integrations",
        "revanced-website",
        "revanced-cli",
        "revanced-manager",
    ]
    api-version = 1
  2. Run the program
  3. Go to http://127.0.0.1:8080/v1/patches/latest/list
  4. You should see the stacktrace in the logs and the incomplete HTTP response:

    image

Stacktrace:

com.fasterxml.jackson.databind.JsonMappingException: org.jetbrains.kotlin.name.ClassId (through reference chain: java.util.ArrayList[5]->app.revanced.library.PatchUtils$Json$FullJsonPatch["dependencies"]->java.util.LinkedHashSet[0])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:402)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:373)
    at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:345)
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:153)
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:479)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:318)
    at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4719)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:3923)
    at app.revanced.library.PatchUtils$Json.serialize(PatchUtils.kt:120)
    at app.revanced.library.PatchUtils$Json.serialize$default(PatchUtils.kt:110)
    at app.revanced.api.modules.RoutingKt$configureRouting$1$1$2$1$3$1.invokeSuspend(Routing.kt:183)
    at app.revanced.api.modules.RoutingKt$configureRouting$1$1$2$1$3$1.invoke(Routing.kt)
    at app.revanced.api.modules.RoutingKt$configureRouting$1$1$2$1$3$1.invoke(Routing.kt)
    at io.ktor.http.content.OutputStreamContent$writeTo$2.invokeSuspend(OutputStreamContent.kt:28)
    at io.ktor.http.content.OutputStreamContent$writeTo$2.invoke(OutputStreamContent.kt)
    at io.ktor.http.content.OutputStreamContent$writeTo$2.invoke(OutputStreamContent.kt)
    at io.ktor.http.content.BlockingBridgeKt.withBlocking(BlockingBridge.kt:28)
    at io.ktor.http.content.OutputStreamContent.writeTo(OutputStreamContent.kt:24)
    at io.ktor.server.engine.BaseApplicationResponse$respondWriteChannelContent$2$1.invokeSuspend(BaseApplicationResponse.kt:174)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
    at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
    at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Caused by: java.lang.ClassNotFoundException: org.jetbrains.kotlin.name.ClassId
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.parseType(KDeclarationContainerImpl.kt:291)
    at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.loadReturnType(KDeclarationContainerImpl.kt:306)
    at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.findMethodBySignature(KDeclarationContainerImpl.kt:216)
    at kotlin.reflect.jvm.internal.KPropertyImplKt.computeCallerForAccessor(KPropertyImpl.kt:263)
    at kotlin.reflect.jvm.internal.KPropertyImplKt.access$computeCallerForAccessor(KPropertyImpl.kt:1)
    at kotlin.reflect.jvm.internal.KPropertyImpl$Getter$caller$2.invoke(KPropertyImpl.kt:180)
    at kotlin.reflect.jvm.internal.KPropertyImpl$Getter$caller$2.invoke(KPropertyImpl.kt:179)
    at kotlin.SafePublicationLazyImpl.getValue(LazyJVM.kt:107)
    at kotlin.reflect.jvm.internal.KPropertyImpl$Getter.getCaller(KPropertyImpl.kt:179)
    at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:64)
    at kotlin.reflect.jvm.ReflectJvmMapping.getJavaGetter(ReflectJvmMapping.kt:49)
    at com.fasterxml.jackson.module.kotlin.KotlinAnnotationIntrospector.getRequiredMarkerFromCorrespondingAccessor(KotlinAnnotationIntrospector.kt:134)
    at com.fasterxml.jackson.module.kotlin.KotlinAnnotationIntrospector.hasRequiredMarker(KotlinAnnotationIntrospector.kt:129)
    at com.fasterxml.jackson.module.kotlin.KotlinAnnotationIntrospector.access$hasRequiredMarker(KotlinAnnotationIntrospector.kt:28)
    at com.fasterxml.jackson.module.kotlin.KotlinAnnotationIntrospector$hasRequiredMarker$hasRequired$1.invoke(KotlinAnnotationIntrospector.kt:45)
    at com.fasterxml.jackson.module.kotlin.KotlinAnnotationIntrospector$hasRequiredMarker$hasRequired$1.invoke(KotlinAnnotationIntrospector.kt:38)
    at com.fasterxml.jackson.module.kotlin.ReflectionCache.javaMemberIsRequired(ReflectionCache.kt:102)
    at com.fasterxml.jackson.module.kotlin.KotlinAnnotationIntrospector.hasRequiredMarker(KotlinAnnotationIntrospector.kt:38)
    at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.hasRequiredMarker(AnnotationIntrospectorPair.java:326)
    at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.hasRequiredMarker(AnnotationIntrospectorPair.java:326)
    at com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder.getMetadata(POJOPropertyBuilder.java:230)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._anyIndexed(POJOPropertiesCollector.java:1325)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._sortProperties(POJOPropertiesCollector.java:1227)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:494)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getJsonValueAccessor(POJOPropertiesCollector.java:286)
    at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findJsonValueAccessor(BasicBeanDescription.java:258)
    at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByAnnotations(BasicSerializerFactory.java:393)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:225)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:174)
    at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1507)
    at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1475)
    at com.fasterxml.jackson.databind.SerializerProvider.findContentValueSerializer(SerializerProvider.java:759)
    at com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap.findAndAddSecondarySerializer(PropertySerializerMap.java:98)
    at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase._findAndAddDynamic(AsArraySerializerBase.java:325)
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:137)
    ... 31 common frames omitted
k163377 commented 8 months ago

As far as Cause is concerned, it looks like a Kotlin version mismatch. The ClassId is not present in 1.9.22 while the latest seems to have it. https://github.com/JetBrains/kotlin/blob/44ed2e94f57d63b380a81ad9dceba95b57f2f33d/core/compiler.common/src/org/jetbrains/kotlin/name/ClassId.kt#L56 https://github.com/JetBrains/kotlin/releases/tag/v1.9.22 https://github.com/JetBrains/kotlin/blob/a7ac89d4315a9d5cdcd70c8f31bf5b7d37fe6a4a/core/compiler.common/src/org/jetbrains/kotlin/name/ClassId.kt#L56 https://github.com/JetBrains/kotlin/releases/tag/v2.0.0-Beta3

So it appears that you are referencing code compiled with a higher version of Kotlin from an incompatible Kotlin version. Since there is no use of ClassId in kotlin-module, this appears to be a flaw in the project configuration and not kotlin-module.

If you need further investigation, please submit a reproduction with a minimal configuration that shows kotlin-module as the cause.

oSumAtrIX commented 8 months ago

This is a good find. I think I'll investigate further on this, until then my question should be solved, thanks!