From 567d6cf9a5268240d463f3f93bf7e8602c7df7d9 Mon Sep 17 00:00:00 2001 From: kailyak <141789731+kailyak@users.noreply.github.com> Date: Fri, 28 Jun 2024 07:56:37 -0700 Subject: [PATCH] Use Jackson2ObjectMapperBuilder and add jdk8 serialization support --- .../build.gradle.kts | 1 + .../sse/DgsSSESubscriptionHandler.kt | 5 +-- .../sse/DgsSSESubscriptionHandlerTest.kt | 35 +++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/graphql-dgs-subscriptions-sse/build.gradle.kts b/graphql-dgs-subscriptions-sse/build.gradle.kts index 1ed07a81f..84e117415 100644 --- a/graphql-dgs-subscriptions-sse/build.gradle.kts +++ b/graphql-dgs-subscriptions-sse/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(project(":graphql-dgs")) implementation(project(":graphql-dgs-subscription-types")) + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.springframework:spring-web") implementation("org.springframework:spring-webmvc") diff --git a/graphql-dgs-subscriptions-sse/src/main/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandler.kt b/graphql-dgs-subscriptions-sse/src/main/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandler.kt index 8f6a285bd..a659e9ae3 100644 --- a/graphql-dgs-subscriptions-sse/src/main/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandler.kt +++ b/graphql-dgs-subscriptions-sse/src/main/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandler.kt @@ -16,7 +16,7 @@ package com.netflix.graphql.dgs.subscriptions.sse -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.graphql.dgs.DgsQueryExecutor import com.netflix.graphql.types.subscription.QueryPayload import com.netflix.graphql.types.subscription.SSEDataPayload @@ -32,6 +32,7 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.http.MediaType import org.springframework.http.codec.ServerSentEvent +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody @@ -139,7 +140,7 @@ open class DgsSSESubscriptionHandler(open val dgsQueryExecutor: DgsQueryExecutor } companion object { - private val mapper = jacksonObjectMapper() + private val mapper: ObjectMapper = Jackson2ObjectMapperBuilder.json().build() private val logger: Logger = LoggerFactory.getLogger(DgsSSESubscriptionHandler::class.java) } } diff --git a/graphql-dgs-subscriptions-sse/src/test/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandlerTest.kt b/graphql-dgs-subscriptions-sse/src/test/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandlerTest.kt index 28c2d55f7..4d572910b 100644 --- a/graphql-dgs-subscriptions-sse/src/test/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandlerTest.kt +++ b/graphql-dgs-subscriptions-sse/src/test/kotlin/com/netflix/graphql/dgs/subscriptions/sse/DgsSSESubscriptionHandlerTest.kt @@ -44,6 +44,7 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.request import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import reactor.core.publisher.Flux import java.util.Base64 +import java.util.Optional @Disabled("Avoiding stuck builds") @WebMvcTest(DgsSSESubscriptionHandler::class, DgsSSESubscriptionHandlerTest.App::class) @@ -172,4 +173,38 @@ internal class DgsSSESubscriptionHandlerTest { assertEquals("message 1", messages[0].data) assertEquals("message 2", messages[1].data) } + + @Test + fun `success with Optional types`() { + val query = "subscription { stocks { name, price }}" + val queryPayload = QueryPayload(operationName = "MySubscription", query = query) + val encodedQuery = Base64.getEncoder().encodeToString(mapper.writeValueAsBytes(queryPayload)) + + val publisher = Flux.just( + ExecutionResultImpl.newExecutionResult().data(Optional.of("optional message")).build(), + ExecutionResultImpl.newExecutionResult().data(Optional.empty()).build() + ) + val executionResult = ExecutionResultImpl.newExecutionResult().data(publisher).build() + + `when`(dgsQueryExecutor.execute(eq(query), any())).thenReturn(executionResult) + + val result = mockMvc.perform(get("/subscriptions").param("query", encodedQuery)) + .andExpect(request().asyncStarted()) + .andExpect(status().is2xxSuccessful) + .andReturn() + + mockMvc.perform(asyncDispatch(result)) + .andExpect(content().contentType(MediaType.TEXT_EVENT_STREAM)) + .andReturn() + + val messages = result.response.contentAsString.lineSequence() + .filter { line -> line.startsWith("data:") } + .map { line -> line.substring("data:".length) } + .map { line -> mapper.readValue(line) } + .toList() + + assertEquals(2, messages.size) + assertEquals("optional message", messages[0].data) + assertEquals(null, messages[1].data) + } }