Netflix / Netflix/dgs-codegen

ZoneId mapping not working when serializing

Open
#368 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
217
Forks
116
PR merge metrics
No merged PRs in 30d

Description

I have a custom scalar like this:

scalar TimezoneName

which is implemented like this:

@DgsScalar(name = "TimezoneName")
public class TimezoneNameScalar implements Coercing<ZoneId, String> {}

With a gradle config like this:

generateJava {
    generateClient = true
    typeMapping = [
        'TimezoneName': 'java.time.ZoneId',
        'LocalDate': 'java.time.LocalDate',
  ]
}

And works just fine. E.g. you can have this:

input Filters {
  dateFrom: LocalDate!
  dateTo: LocalDate!
  timezoneName: TimezoneName!
}

as

{ 
  "dateFrom": "2022-01-01",
  "dateTo": "2022-01-02",
  "timezoneName": "Europe/London"
}

However, when I use this in a test with the query builder, I get an error:

GraphQLQueryRequest queryRequest = new GraphQLQueryRequest(
  new MyGraphQLQuery.Builder()
    .filters(
      new Filters(
        LocalDate.parse("2020-01-01"),
        LocalDate.parse("2020-01-02"),
        ZoneId.of("Europe/London")
      )
    )
  )
  .build()
  // select fields
);

queryRequest.serialize();

leads to:

 java.lang.reflect.InaccessibleObjectException: Unable to make field private static final long java.time.ZoneRegion.serialVersionUID accessible: module java.base does not "opens java.time" to unnamed module @5965d37
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
        at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
        at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)
        at com.netflix.graphql.dgs.client.codegen.InputValueSerializer.serialize(InputValueSerializer.kt:68)
        at com.netflix.graphql.dgs.client.codegen.InputValueSerializer.serialize(InputValueSerializer.kt:78)
        at com.netflix.graphql.dgs.client.codegen.InputValueSerializer.serialize(InputValueSerializer.kt:78)
        at com.netflix.graphql.dgs.client.codegen.GraphQLQueryRequest.serialize(GraphQLQueryRequest.kt:47)

I am not quite sure how to fix this... I googled a bit and found some things to add arguments to java (e.g. see https://stackoverflow.com/questions/70412805/what-does-this-error-mean-java-lang-reflect-inaccessibleobjectexception-unable), but this seems a bit.. less than ideal to me. Not sure if there is something that can be done to avoid this issue?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with InputValueSerializer.kt around line 68 and GraphQLQueryRequest.kt around line 47, then reproduce the issue with the shown ZoneId input and queryRequest.serialize(). Determine how custom scalar values are serialized without triggering reflective access to java.time, and consider the issue complete when this example serializes without the InaccessibleObjectException.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.