Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resteasy and Kotlinx Serialization #9003

Closed
akoufa opened this issue May 1, 2020 · 11 comments
Closed

Resteasy and Kotlinx Serialization #9003

akoufa opened this issue May 1, 2020 · 11 comments
Assignees
Labels
area/kotlin kind/enhancement New feature or request kind/extension-proposal Discuss and Propose new extensions
Milestone

Comments

@akoufa
Copy link

akoufa commented May 1, 2020

Description

Hello to all. If I am not mistaken, currently the only way to automatically serialise and deserialise objects that we receive/send in the Resteasy HTTP endpoints is using either JsonB or Jackson. I would therefore kindly ask if the default Kotlin serialisation way of using kotlinx.serialization is planned to be supported by Quarkus as a RestEasy extension. As me and I think lot of the current and future Quarkus users, like being able to use Kotlin in Quarkus projects, we would be grateful if kotlinx.serialization and coroutines will be considered as important targets for Quarkus near term future as they are the finishing touches on the decent support of Kotlin in Quarkus.

Thank you so much for your effort.

@akoufa akoufa added the kind/enhancement New feature or request label May 1, 2020
@geoand
Copy link
Contributor

geoand commented May 1, 2020

cc @evanchooly

@geoand geoand added this to Todo in Kotlin roadmap via automation Jun 30, 2020
@emmanuelbernard emmanuelbernard removed this from Todo in Kotlin roadmap Jun 30, 2020
@emmanuelbernard emmanuelbernard added this to Todo in Kotlin roadmap via automation Jun 30, 2020
@emmanuelbernard emmanuelbernard added the kind/extension-proposal Discuss and Propose new extensions label Jun 30, 2020
@emmanuelbernard emmanuelbernard added this to Backlog in General Roadmap (deprecated) via automation Jun 30, 2020
@emmanuelbernard emmanuelbernard moved this from Backlog to 1.8 plan - Early September in General Roadmap (deprecated) Jun 30, 2020
@n1hility
Copy link
Member

@evanchooly Any updates here, or should this be moved to 1.9?

@evanchooly
Copy link
Member

evanchooly commented Sep 11, 2020 via email

@n1hility n1hility moved this from 1.8 plan - Early September to 1.9 plan - Early October in General Roadmap (deprecated) Sep 23, 2020
@n1hility n1hility moved this from 1.9 plan - Early October to 1.10 plan early november in General Roadmap (deprecated) Sep 23, 2020
@xiaoyunwu
Copy link

And update on this? I am getting the following "Class initialization of kotlinx.serialization.internal.IntSerializer failed." error when try to build native image.

@n1hility n1hility moved this from 1.10 Done - early november to 1.12 Plan in General Roadmap (deprecated) Jan 15, 2021
@n1hility n1hility moved this from 1.12 Plan to Backlog in General Roadmap (deprecated) Jan 15, 2021
@xiaoyunwu
Copy link

xiaoyunwu commented Jan 16, 2021

@n1hility is there anything pointer on how this should be done? So that others can take a crack at it? Or any suggestion on how these used kotlinx serialization extensively move to quakrus? Many thanks.

@evanchooly evanchooly self-assigned this Jul 12, 2021
@evanchooly evanchooly moved this from Todo to Doing in Kotlin roadmap Jul 12, 2021
@geoand
Copy link
Contributor

geoand commented Jul 27, 2021

@evanchooly is looking into this (and I'll be helping if necessary).
The plan is to introduce support into RESTEasy Reactive

@vladimirfx
Copy link

vladimirfx commented Dec 12, 2021

Let me describe the use case:
Our team develops many microservices and integrations mainly on Kotlin. About 50% of it is Quarkus based. Almost all need some kind of serialization and the default (most used) option is Jackson. With Jackson, we constantly fight with issues related to Kotlin-Jackson-Native Image compatibility.
Simplest example:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
data class ServerRequest(
    val lastName: String,
    val firstName: String,
    val documentNumber: String,
    val typeOfDocument: String,
    val mobilePhone: String?,
    val dateOfBirth: String?,
)

Do not work even on JVM because Jackson does not use the constructor (why???). Ok, fix this by adding to build:

    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

Quarkus do a good job and do register needed Jackson module. Works fine on JVM!
This module is nanoservice (c) and 'pay' 200Mb+ RAM for running it is crazy. Let's build Native Image!

Not so fast - #8479

So, the fight is proceed. Hours of debugging and we remove jackson-module-kotlin module and build workaround:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
data class ServerRequest @JsonCreator constructor(
    val lastName: String,
    val firstName: String,
    val documentNumber: String,
    val typeOfDocument: String,
    val mobilePhone: String?,
    val dateOfBirth: String?,
)

It is just one example of an annoying experience that came from Jackson for Kotlin developer. For simple cases, we migrated to JSON-B.

How to fix it? Kotlinx Serialization - it just works in our experience - Ktor (handmade native build), Spring Native. It builds serializers at compile time and this is a gamechanger in the native world. As a bonus, you actually know what you get serialized instead of hoping (and praying) for a good result.

Please support us - your Kotlin fans...

@geoand
Copy link
Contributor

geoand commented Dec 12, 2021

The is work in progress on this. You can track it here

@geoand
Copy link
Contributor

geoand commented Jan 9, 2022

#21318 has been merged (and some subsequent fixes have been applied), so we can close this.

The first release that will contain this support is 2.7.
Note that Kotlin Serialization support is only provided for RESTEasy Reactive

@geoand geoand closed this as completed Jan 9, 2022
Kotlin roadmap automation moved this from Doing to Done Jan 9, 2022
@geoand geoand added this to the 2.7 - main milestone Jan 9, 2022
@vladimirfx
Copy link

Tryed 2.7.0.CR1 on one-method microservice:

@ApplicationScoped
@Path("horoscope")
class Horoscopes{
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("daily")
    suspend fun daily(): List<Horoscope> {
       // impl here
    }
}

@Serializable
data class Horoscope(val id: Long, val text: String)

Error on JVM and Native:


2022-01-20 12:53:28,534 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (vert.x-eventloop-thread-0) HTTP Request to /horoscope/daily failed, error id: 3b5d1d0c-c940-4b56-b087-bcf0a189e13c-1: kotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
	at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
	at kotlinx.serialization.SerializersKt__SerializersJvmKt.serializer(SerializersJvm.kt:59)
	at kotlinx.serialization.SerializersKt.serializer(Unknown Source)
	at kotlinx.serialization.SerializersKt__SerializersJvmKt.serializer(SerializersJvm.kt:30)
	at kotlinx.serialization.SerializersKt.serializer(Unknown Source)
	at io.quarkus.kotlin.serialization.KotlinSerializationMessageBodyWriter.writeResponse(KotlinSerializationMessageBodyWriter.kt:42)
	at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:207)
	at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:178)
	at org.jboss.resteasy.reactive.server.core.serialization.DynamicEntityWriter.write(DynamicEntityWriter.java:90)
	at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:32)
	at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:15)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141)
	at org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$1$1.handle(VertxResteasyReactiveRequestContext.java:85)
	at org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$1$1.handle(VertxResteasyReactiveRequestContext.java:82)
	at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
	at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:63)
	at io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:38)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)

That is because ServerResourceMethod.returnType of hander method is detected as java.lang.Object. Should I file a separate bug or it is normal for suspend method?

@geoand
Copy link
Contributor

geoand commented Jan 20, 2022

It's definitely a bug. I'll take care of it.

Thanks for trying it out and reporting!

geoand added a commit to geoand/quarkus that referenced this issue Jan 20, 2022
This was not a problem with Jackson or Jsonb, because they
used the object class to determine the type of serializer,
but it is needed for Kotlin serialization which actually
used the generic type provided in the MessageBodyWriter
params to determine the serializer

Addresses: #quarkusio#9003 (comment)
geoand added a commit to geoand/quarkus that referenced this issue Jan 20, 2022
This was not a problem with Jackson or Jsonb, because they
used the object class to determine the type of serializer,
but it is needed for Kotlin serialization which actually
used the generic type provided in the MessageBodyWriter
params to determine the serializer

Addresses: #quarkusio#9003 (comment)
gsmet pushed a commit to gsmet/quarkus that referenced this issue Jan 21, 2022
This was not a problem with Jackson or Jsonb, because they
used the object class to determine the type of serializer,
but it is needed for Kotlin serialization which actually
used the generic type provided in the MessageBodyWriter
params to determine the serializer

Addresses: #quarkusio#9003 (comment)
(cherry picked from commit c273a64)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/kotlin kind/enhancement New feature or request kind/extension-proposal Discuss and Propose new extensions
Projects
Development

No branches or pull requests

8 participants