leangen / graphql-spqr

Build a GraphQL service in seconds
Apache License 2.0
1.09k stars 179 forks source link

Question about Subscription response #411

Closed vadrem closed 1 year ago

vadrem commented 2 years ago

Hi can anyone explain me following situation.

I have a simple subscription which work, I publish ZonedDateTime:

@GraphQLSubscription(name = "sendMessage")
  public Publisher<Object> sendMessage()
  {
    return Flux.create(subscriber -> subscriber.next(ZonedDateTime.now()), FluxSink.OverflowStrategy.LATEST);
  }

I receive data as string - OK:

"data": {
    "sendMessage": "2021-10-06T22:47:08.014908+02:00[Europe/Berlin]"
  }

If I publish Object with property ZonedDateTime:

@GraphQLSubscription(name = "sendMessage")
  public Publisher<Object> sendMessage()
  {
    return Flux.create(subscriber -> subscriber.next(new Test()), FluxSink.OverflowStrategy.LATEST);
  }

private static class Test
  {
    private final ZonedDateTime zonedDateTime = ZonedDateTime.now();

    @Nonnull
    public ZonedDateTime getZonedDateTime()
    {
      return this.zonedDateTime;
    }
  }

Then I have other picture - NOT OK:

"data": {
    "sendMessage": {
      "zonedDateTime": {
        "offset": {
          "totalSeconds": 7200,
          "id": "+02:00",
          "rules": {
            "fixedOffset": true,
            "transitions": [],
            "transitionRules": []
          }
        },
        "zone": {
          "id": "Europe/Berlin",
          "rules": {
            "fixedOffset": false,
            "transitions": [
              {
                "offsetBefore": {
                  "totalSeconds": 3208,
                  "id": "+00:53:28",
                  "rules": {
                    "fixedOffset": true,
                    "transitions": [],
                    "transitionRules": []
..........

I use graphql-spqr-spring-boot-starter 0.0.6. Any suggestion why its happens and how can I influence on it (ObjectMapper config not help)?

kaqqao commented 1 year ago

The problem is that your return type is Publisher<Object> instead of Publisher<Test>. When SPQR is analyzing your classes, and sees Object as the static type, it has no way to know what will be inside at runtime, thus is has no means to map the type as anything other than scalar object (basically "a blob"). The entire object is then returned as-is, without any sub-selection possible. And from there it gets serialized to JSON in wherever way your web layer is configured to do so.

To achieve what you want, first you have to :

a) be precise with your types: set the return type to Publisher<Test>, b) properly select the sub-fields: subscription Time {sendMessage { zonedDateTime } }

This way the types will get mapped properly and you'll receive the usual GraphQL result.