From c273a64151696e1dd372fc1ecd00783920f49065 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Thu, 20 Jan 2022 15:14:30 +0200 Subject: [PATCH] Use proper return type when indexing suspend functions 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: #https://github.com/quarkusio/quarkus/issues/9003#issuecomment-1017301945 --- .../common/processor/EndpointIndexer.java | 17 +++++----- .../io/quarkus/it/kotser/GreetingResource.kt | 12 +++++++ .../io/quarkus/it/kotser/ResourceTest.kt | 33 +++++++++++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index e009dc1918a2b..9fd183e22c1bd 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -553,9 +553,10 @@ private ResourceMethod createResourceMethod(ClassInfo currentClassInfo, ClassInf } } - Type nonAsyncReturnType = getNonAsyncReturnType(methodContext.containsKey(METHOD_CONTEXT_CUSTOM_RETURN_TYPE_KEY) + Type methodContextReturnTypeOrReturnType = methodContext.containsKey(METHOD_CONTEXT_CUSTOM_RETURN_TYPE_KEY) ? (Type) methodContext.get(METHOD_CONTEXT_CUSTOM_RETURN_TYPE_KEY) - : currentMethodInfo.returnType()); + : currentMethodInfo.returnType(); + Type nonAsyncReturnType = getNonAsyncReturnType(methodContextReturnTypeOrReturnType); addWriterForType(additionalWriters, nonAsyncReturnType); String[] produces = extractProducesConsumesValues(getAnnotationStore().getAnnotation(currentMethodInfo, PRODUCES), @@ -622,7 +623,8 @@ private ResourceMethod createResourceMethod(ClassInfo currentClassInfo, ClassInf toClassName(currentMethodInfo.returnType(), currentClassInfo, actualEndpointInfo, index)) // FIXME: resolved arguments ? .setReturnType( - determineReturnType(currentMethodInfo, typeArgMapper, currentClassInfo, actualEndpointInfo, index)); + determineReturnType(methodContextReturnTypeOrReturnType, typeArgMapper, currentClassInfo, + actualEndpointInfo, index)); if (httpMethod == null) { handleClientSubResource(method, currentMethodInfo, index); @@ -686,13 +688,12 @@ protected boolean doesMethodHaveBlockingSignature(MethodInfo info) { return true; } - private String determineReturnType(MethodInfo info, TypeArgMapper typeArgMapper, ClassInfo currentClassInfo, + private String determineReturnType(Type returnType, TypeArgMapper typeArgMapper, ClassInfo currentClassInfo, ClassInfo actualEndpointInfo, IndexView index) { - Type type = info.returnType(); - if (type.kind() == Type.Kind.TYPE_VARIABLE) { - type = resolveTypeVariable(type.asTypeVariable(), currentClassInfo, actualEndpointInfo, index); + if (returnType.kind() == Type.Kind.TYPE_VARIABLE) { + returnType = resolveTypeVariable(returnType.asTypeVariable(), currentClassInfo, actualEndpointInfo, index); } - return AsmUtil.getSignature(type, typeArgMapper); + return AsmUtil.getSignature(returnType, typeArgMapper); } protected abstract boolean handleBeanParam(ClassInfo actualEndpointInfo, Type paramType, MethodParameter[] methodParameters, diff --git a/integration-tests/kotlin-serialization/src/main/kotlin/io/quarkus/it/kotser/GreetingResource.kt b/integration-tests/kotlin-serialization/src/main/kotlin/io/quarkus/it/kotser/GreetingResource.kt index a2cd5fc08712c..723eaf2f12d81 100644 --- a/integration-tests/kotlin-serialization/src/main/kotlin/io/quarkus/it/kotser/GreetingResource.kt +++ b/integration-tests/kotlin-serialization/src/main/kotlin/io/quarkus/it/kotser/GreetingResource.kt @@ -17,6 +17,18 @@ class GreetingResource { return Person("Jim Halpert") } + @Path("suspend") + @GET + @Produces(MediaType.APPLICATION_JSON) + suspend fun suspendHello(): Person { + return Person("Jim Halpert") + } + + @Path("suspendList") + @GET + @Produces(MediaType.APPLICATION_JSON) + suspend fun suspendHelloList() = listOf(Person("Jim Halpert")) + @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) diff --git a/integration-tests/kotlin-serialization/src/test/kotlin/io/quarkus/it/kotser/ResourceTest.kt b/integration-tests/kotlin-serialization/src/test/kotlin/io/quarkus/it/kotser/ResourceTest.kt index aa5d8efa84182..f06c828274e12 100644 --- a/integration-tests/kotlin-serialization/src/test/kotlin/io/quarkus/it/kotser/ResourceTest.kt +++ b/integration-tests/kotlin-serialization/src/test/kotlin/io/quarkus/it/kotser/ResourceTest.kt @@ -23,6 +23,39 @@ open class ResourceTest { )) } + @Test + fun testSuspendGet() { + given() + .`when`().get("/suspend") + .then() + .statusCode(200) + .body(`is`( + """ + { + "name": "Jim Halpert", + "defaulted": "hi there!" + }""".trimIndent() + )) + } + + @Test + fun testSuspendGetList() { + given() + .`when`().get("/suspendList") + .then() + .statusCode(200) + .body(`is`( + """ +[ + { + "name": "Jim Halpert", + "defaulted": "hi there!" + } +] +""".trimIndent() + )) + } + @Test fun testPost() { given()