dgs-framework icon indicating copy to clipboard operation
dgs-framework copied to clipboard

bug: client throws error when parsing response with error.

Open DAVID9SE opened this issue 1 year ago • 2 comments

Hi, I am experiencing an issue when using DGS for integration tests. I am using MonoGraphQLClient and I have my test queries in a file. Everything works fine until I try to test errors. The tests that are supposed to check if directives to check ranges work. The client throws an error instead of parsing the response.

This is what the tested endpoint returns to the client:

{
  "errors": [
    {
      "message": "The field topicsProjects must be between $1 and $100",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ],
      "path": [
        "topicsProjectsQueries",
        "topicsProjects"
      ],
      "extensions": {
        "classification": {
          "type": "ExtendedValidationError",
          "validatedPath": [
            "topicsProjectsQueries",
            "topicsProjects",
            "paging",
            "size"
          ],
          "constraint": "@Range"
        }
      }
    }
  ],
  "data": null
}

This is the error I get.

com.jayway.jsonpath.spi.mapper.MappingException: java.lang.IllegalArgumentException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
 at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: java.util.ArrayList[0]->com.netflix.graphql.dgs.client.GraphQLError["extensions"]->com.netflix.graphql.dgs.client.GraphQLErrorExtensions["classification"])
	at com.jayway.jsonpath.spi.mapper.JacksonMappingProvider.map(JacksonMappingProvider.java:58)
	at com.jayway.jsonpath.internal.JsonContext.convert(JsonContext.java:121)
	at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:103)
	at com.netflix.graphql.dgs.client.GraphQLResponse.<init>(GraphQLResponse.kt:52)
	at com.netflix.graphql.dgs.client.WebClientGraphQLClient.handleResponse(WebClientGraphQLClient.kt:146)
	at com.netflix.graphql.dgs.client.WebClientGraphQLClient.access$handleResponse(WebClientGraphQLClient.kt:42)
	at com.netflix.graphql.dgs.client.WebClientGraphQLClient$reactiveExecuteQuery$3.invoke(WebClientGraphQLClient.kt:136)
	at com.netflix.graphql.dgs.client.WebClientGraphQLClient$reactiveExecuteQuery$3.invoke(WebClientGraphQLClient.kt:136)
	at com.netflix.graphql.dgs.client.WebClientGraphQLClient.reactiveExecuteQuery$lambda$3(WebClientGraphQLClient.kt:136)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:113)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:245)
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122)
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:122)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129)
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299)
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337)
	at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2071)
	at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144)
	at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:413)
	at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:431)
	at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:485)
	at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:712)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:800)
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:499)
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:397)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	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:840)
	Suppressed: java.lang.Exception: #block terminated with an error
		at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:102)
		at reactor.core.publisher.Mono.block(Mono.java:1712)
		at cz.cvut.fel.czm.temataprojectslogic.BaseCT.graphQlRequestFromFile(BaseCT.kt:67)

The method where the error is thrown.

fun graphQlRequestFromFile(file: String, variables: Map<String, Any> = emptyMap()): GraphQLResponse {
        val query = javaClass.getResource(file)?.readText()
            ?: throw IllegalStateException("Cannot read query")
        return graphQlTestClient.reactiveExecuteQuery(query, variables).block() ?: throw IllegalStateException(
            "Null response"
        )
    }

Expected behavior

I would expect the client to parse the response normally.

Actual behavior

The response is not parsed and an error is invoked.

Steps to reproduce

Use the client to request from an endpoint that returns an error(Like the one above.).

Thanks a lot

DAVID9SE avatar Feb 12 '24 13:02 DAVID9SE

I believe this issue was fixed in v8.2.5 (see #1802). What version of DGS are you on?

kilink avatar Feb 13 '24 16:02 kilink

Hey, we are on 7.XX. I will migrate (it will take some time since there are some breaking changes.) to 8.XX and see if the issue persists.

DAVID9SE avatar Feb 15 '24 13:02 DAVID9SE

Fixed in 7.X

DAVID9SE avatar Aug 16 '24 13:08 DAVID9SE