Repository: smallrye/smallrye-graphql
Issue: Graphql client handle UUID

Hi, I am writing tests for my graphql endpoint like follows

Endpoint
```java
package graphql

import types.Organization;
import io.quarkus.security.Authenticated;
@GraphQLApi
public class OrganizationResource {

    @Authenticated
    @Query
    public Organization organization(@NonNull UUID id) {
        return Organization.builder().id(id).value("test").build()
    }
}
```

Graphql type
```java
package types;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

import java.util.UUID;

@AllArgsConstructor
@Data
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class Organization {
    private UUID id;
    private String value;
}

```

Graphql client
```java
@GraphQlClientApi
interface Client {
  Organization organization(@NonNull @Name("id") String id);
}
```

Test
```java
public class OrganizationResourceTest {
   @Test
    public void testOrganizationQuery() {
        var id = UUID.randomUUID()
        var response = graphql.organization(organization.getId().toString());
        assertEquals(id, response.getId());
    }
}
```
but I receive this error 

```
io.smallrye.graphql.client.typesafe.api.GraphQlClientException: errors from service:
- {"message":"Validation error of type SubSelectionNotAllowed: Sub selection not allowed on leaf type String of field id @ 'organization/id'","locations":[{"line":1,"column":59}],"extensions":{"description":"Sub selection not allowed on leaf type String of field id","validationErrorType":"SubSelectionNotAllowed","queryPath":["organization","id"],"classification":"ValidationError"}}
query: query organization($id: String!) { organization(id: $id) {id {mostSigBits leastSigBits} value } }
```

It seems like the client is not mapping the UUID field to a String field which is how the graphql endpoint is returning fields of that type.

Any suggestion on how to handle this case?
Version: smallrye-graphql-client : 1.0.15


Changed files:
client/implementation/src/test/java/test/unit/ScalarBehavior.java
client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/json/JsonStringReader.java
client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/TypeInfo.java
client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/ParameterInfo.java

diff --git a/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/json/JsonStringReader.java b/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/json/JsonStringReader.java
index 3364d70a..24335f2d 100644
--- a/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/json/JsonStringReader.java
+++ b/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/json/JsonStringReader.java
@@ -27,6 +27,8 @@ class JsonStringReader extends Reader<JsonString> {
 
         if (java.util.Date.class.equals(this.type.getRawType()))
             return java.util.Date.from(Instant.parse(value.getString()));
+        if (java.util.UUID.class.equals(this.type.getRawType()))
+            return java.util.UUID.fromString(value.getString());
 
         ConstructionInfo constructor = type.scalarConstructor()
                 .orElseThrow(() -> new GraphQlClientValueException(location, value));
diff --git a/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/ParameterInfo.java b/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/ParameterInfo.java
index 6a1ddf9a..418ad1e6 100644
--- a/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/ParameterInfo.java
+++ b/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/ParameterInfo.java
@@ -63,6 +63,7 @@ public class ParameterInfo {
             case "String":
             case "char":
             case "Character":
+            case "UUID":
                 return "String";
             case "boolean":
             case "Boolean":
diff --git a/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/TypeInfo.java b/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/TypeInfo.java
index 6b9cbbcf..1173d8ed 100644
--- a/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/TypeInfo.java
+++ b/client/implementation/src/main/java/io/smallrye/graphql/client/typesafe/impl/reflection/TypeInfo.java
@@ -126,7 +126,12 @@ public class TypeInfo {
     }
 
     private boolean isGraphQlField(Field field) {
-        return !isStatic(field.getModifiers()) && !isTransient(field.getModifiers());
+        return !isStatic(field.getModifiers()) && !isSynthetic(field.getModifiers()) && !isTransient(field.getModifiers());
+    }
+
+    /** Modifier.isSynthetic is package private */
+    private static boolean isSynthetic(int mod) {
+        return (mod & 0x00001000) != 0;
     }
 
     public boolean isOptional() {
@@ -146,6 +151,7 @@ public class TypeInfo {
                 || CharSequence.class.isAssignableFrom(getRawType())
                 || Character.class.equals(getRawType()) // has a valueOf(char), not valueOf(String)
                 || java.util.Date.class.equals(getRawType())
+                || java.util.UUID.class.equals(getRawType())
                 || scalarConstructor().isPresent();
     }
 
diff --git a/client/implementation/src/test/java/test/unit/ScalarBehavior.java b/client/implementation/src/test/java/test/unit/ScalarBehavior.java
index 5a763b11..53047498 100644
--- a/client/implementation/src/test/java/test/unit/ScalarBehavior.java
+++ b/client/implementation/src/test/java/test/unit/ScalarBehavior.java
@@ -15,6 +15,7 @@ import java.time.OffsetTime;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.util.Date;
+import java.util.UUID;
 
 import org.eclipse.microprofile.graphql.Id;
 import org.eclipse.microprofile.graphql.NonNull;
@@ -581,14 +582,26 @@ class ScalarBehavior {
     @GraphQlClientApi
     interface IdApi {
         @Id
-        String idea(@Id String in);
+        String idea(
+                @Id String stringId,
+                @Id long primitiveLongId,
+                @Id int primitiveIntId,
+                @Id Long longId,
+                @Id Integer intId,
+                @Id UUID uuidId);
     }
 
     @GraphQlClientApi
     interface NonNullIdApi {
         @NonNull
         @Id
-        String idea(@NonNull @Id String in);
+        String idea(
+                @NonNull @Id String stringId,
+                @NonNull @Id long primitiveLongId,
+                @NonNull @Id int primitiveIntId,
+                @NonNull @Id Long longId,
+                @NonNull @Id Integer intId,
+                @NonNull @Id UUID uuidId);
     }
 
     @GraphQlClientApi
@@ -706,9 +719,22 @@ class ScalarBehavior {
             fixture.returnsData("'idea':'out'");
             IdApi api = fixture.builder().build(IdApi.class);
 
-            String out = api.idea("in");
-
-            then(fixture.query()).isEqualTo("query idea($in: ID) { idea(in: $in) }");
+            String out = api.idea("stringId", 1L, 2, 3L, 4, UUID.randomUUID());
+
+            then(fixture.query()).isEqualTo("query idea(" +
+                    "$stringId: ID, " +
+                    "$primitiveLongId: ID!, " +
+                    "$primitiveIntId: ID!, " +
+                    "$longId: ID, " +
+                    "$intId: ID, " +
+                    "$uuidId: ID) " +
+                    "{ idea(" +
+                    "stringId: $stringId, " +
+                    "primitiveLongId: $primitiveLongId, " +
+                    "primitiveIntId: $primitiveIntId, " +
+                    "longId: $longId, " +
+                    "intId: $intId, " +
+                    "uuidId: $uuidId) }");
             then(out).isEqualTo("out");
         }
 
@@ -717,9 +743,22 @@ class ScalarBehavior {
             fixture.returnsData("'idea':'out'");
             NonNullIdApi api = fixture.builder().build(NonNullIdApi.class);
 
-            String out = api.idea("in");
-
-            then(fixture.query()).isEqualTo("query idea($in: ID!) { idea(in: $in) }");
+            String out = api.idea("stringId", 1L, 2, 3L, 4, UUID.randomUUID());
+
+            then(fixture.query()).isEqualTo("query idea(" +
+                    "$stringId: ID!, " +
+                    "$primitiveLongId: ID!, " +
+                    "$primitiveIntId: ID!, " +
+                    "$longId: ID!, " +
+                    "$intId: ID!, " +
+                    "$uuidId: ID!) " +
+                    "{ idea(" +
+                    "stringId: $stringId, " +
+                    "primitiveLongId: $primitiveLongId, " +
+                    "primitiveIntId: $primitiveIntId, " +
+                    "longId: $longId, " +
+                    "intId: $intId, " +
+                    "uuidId: $uuidId) }");
             then(out).isEqualTo("out");
         }
 
@@ -1015,4 +1054,53 @@ class ScalarBehavior {
             then(value).isEqualTo(Date.from(out));
         }
     }
+
+    @GraphQlClientApi
+    interface UuidApi {
+        UUID foo(UUID uuid, @Id UUID id);
+    }
+
+    @GraphQlClientApi
+    interface NestedUuidIdApi {
+        NestedUuidId foo(NestedUuidId uuid);
+    }
+
+    static class NestedUuidId {
+        @Id
+        UUID id;
+    }
+
+    @Nested
+    class UuidBehavior {
+        @Test
+        void shouldCallUuidQuery() {
+            UUID in1 = UUID.randomUUID();
+            UUID in2 = UUID.randomUUID();
+            UUID out = UUID.randomUUID();
+            fixture.returnsData("'foo':'" + out + "'");
+            UuidApi api = fixture.build(UuidApi.class);
+
+            UUID value = api.foo(in1, in2);
+
+            then(fixture.query()).isEqualTo("query foo($uuid: String, $id: ID) { foo(uuid: $uuid, id: $id) }");
+            then(fixture.variables()).isEqualTo("{'uuid':'" + in1 + "','id':'" + in2 + "'}");
+            then(value).isEqualTo(out);
+        }
+
+        @Test
+        void shouldCallNestedUuidIdQuery() {
+            NestedUuidId in = new NestedUuidId();
+            in.id = UUID.randomUUID();
+            NestedUuidId out = new NestedUuidId();
+            out.id = UUID.randomUUID();
+            fixture.returnsData("'foo':{'id':'" + out.id + "'}");
+            NestedUuidIdApi api = fixture.build(NestedUuidIdApi.class);
+
+            NestedUuidId value = api.foo(in);
+
+            then(fixture.query()).isEqualTo("query foo($uuid: NestedUuidIdInput) { foo(uuid: $uuid) {id} }");
+            then(fixture.variables()).isEqualTo("{'uuid':{'id':'" + in.id + "'}}");
+            then(value.id).isEqualTo(out.id);
+        }
+    }
 }