ktorio / ktor

Framework for quickly creating connected applications in Kotlin with minimal effort
https://ktor.io
Apache License 2.0
12.82k stars 1.04k forks source link

ktor client's 1.1.1 serialization is broken #859

Closed alexvas closed 5 years ago

alexvas commented 5 years ago

Ktor Version

1.1.1

Ktor Engine Used(client or server and name)

ktor-client-apache, ktor-client-jackson

JVM Version, Operating System and Relevant Context

1.8

Feedback

Version 1.0.1 of the library works just fine. Upgrade to 1.1.1 results in the following stacktrace:

kotlinx.serialization.SerializationException: Can't locate argument-less serializer for class navitel.eshop.csob.EchoReq. For generic classes, such as lists, please provid
        at kotlinx.serialization.PlatformUtilsKt.serializer(PlatformUtils.kt:28) ~[kotlinx-serialization-runtime-0.9.1.jar:?]
        at io.ktor.client.features.json.serializer.KotlinxSerializer.lookupSerializerByData(KotlinxSerializer.kt:91) ~[ktor-client-json-jvm-1.1.1.jar:1.1.1]
        at io.ktor.client.features.json.serializer.KotlinxSerializer.write(KotlinxSerializer.kt:67) ~[ktor-client-json-jvm-1.1.1.jar:1.1.1]
        at io.ktor.client.features.json.JsonFeature$Feature$install$1.invokeSuspend(JsonFeature.kt:56) ~[ktor-client-json-jvm-1.1.1.jar:1.1.1]
        at io.ktor.client.features.json.JsonFeature$Feature$install$1.invoke(JsonFeature.kt) ~[ktor-client-json-jvm-1.1.1.jar:1.1.1]
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:278) ~[ktor-utils-jvm-1.1.1.jar:1.1.1]
        at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:63) ~[ktor-utils-jvm-1.1.1.jar:1.1.1]
        at io.ktor.util.pipeline.SuspendFunctionGun.proceed(PipelineContext.kt:137) ~[ktor-utils-jvm-1.1.1.jar:1.1.1]
        at io.ktor.util.pipeline.SuspendFunctionGun.execute(PipelineContext.kt:157) ~[ktor-utils-jvm-1.1.1.jar:1.1.1]
        at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:24) ~[ktor-utils-jvm-1.1.1.jar:1.1.1]
        at io.ktor.client.HttpClient.execute(HttpClient.kt:151) ~[ktor-client-core-jvm-1.1.1.jar:1.1.1]
        at io.ktor.client.call.HttpClientCallKt.call(HttpClientCall.kt:80) ~[ktor-client-core-jvm-1.1.1.jar:1.1.1]
        at io.ktor.client.call.UtilsKt.call(utils.kt:16) ~[ktor-client-core-jvm-1.1.1.jar:1.1.1]

for the:

data class EchoReq(
        /**
         * Merchant’s ID assigned by the payment gateway
         */
        val merchantId: String
) : CsobOutgoing() {
    // etc...
}

configuring builder this way:

    val builder = HttpRequestBuilder().apply {
        contentType(ContentType.Application.Json)
        url.protocol = URLProtocol.HTTPS
        url.host = csobGatewayHost
     }

    if (method == HttpMethod.Post || method == HttpMethod.Put) {
        // не конвертируем исходящее сообщение в Json, это сделает JsonFeature
        builder.body = echoReq
    }
e5l commented 5 years ago

Hi, @alexvas. It looks like a configuration problem. Could you provide the feature configuration code or try explicit specify Jackson serializer?

alexvas commented 5 years ago

Why was not it a configuration problem in verson 1.0.1 then? The (test) client is configured the following way:

    private val httpClient = HttpClient(Apache) {
        install(JsonFeature)

        expectSuccess = false
        engine {
            followRedirects = false
            connectTimeout = 10_000
            socketTimeout = 10_000
            connectionRequestTimeout = 20_000
            customizeClient {
                setDefaultIOReactorConfig(
                        IOReactorConfig.custom().apply {
                            setMaxConnPerRoute(1)
                            setMaxConnTotal(1)
                            setIoThreadCount(1)
                        }.build()
                )
                setThreadFactory(clientThreadFactory)
            }
        }
    }
e5l commented 5 years ago

We use service loader to detect available serializer library. It looks like we have 2 here: Jackson(from the dependency) and kotlinx.serialization from multiplatform ktor-client-json(from 1.1.1).

Could you try to specify Jackson serializer explicitly?(https://ktor.io/clients/http-client/features/json-feature.html#jackson)

Probably we should move kotlinx.serialization in the separate artifact in future.

alexvas commented 5 years ago

Yes, this resolved the issue. Thank you.