Enigmatis / graphql-java-annotations

GraphQL Annotations for Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problems with fields by method

tuxedo0801 opened this issue · comments

commented

I'm using version 8.5 and just started with graphql. I face a strange problem I cannot solve:

I'm using the schema like this:

        GraphQLSchema graphQLSchema = AnnotationsSchemaCreator.newAnnotationsSchema()
                .query(Query.class)
                .setAlwaysPrettify(true) // to set the global prettifier of field names (removes get/set/is prefixes from names)
                .build();

        GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();
        ExecutionResult executionResult = build.execute("{\n"
                + "  allLinks {\n"
                + "    description\n"
                + "    url\n"
                + "  }\n"
                + "}");

        System.out.println(executionResult.getData().toString());

My Query class looks like this:

@GraphQLDescription("this is the query")
public class Query {

    @GraphQLDescription("all links description in query")
    @GraphQLDataFetcher(AllLinksDataFetcher.class)
    @GraphQLField
    private List<Link> allLinks;

    @GraphQLField
    public List<Link> allLinks2(DataFetchingEnvironment env, @GraphQLName("val") String value) {
        System.out.println("dfe: " + env);
        return DummyDatabase.getINSTANCE().links;
    }
}

And the used "Link" class is this:

@GraphQLDescription("Link description")
@GraphQLName("Link")
public class Link {
    
    private final String url;
    private final String description;

    public Link(String url, String description) {
        this.url = url;
        this.description = description;
    }

    @GraphQLField
    @GraphQLDescription("the url")
    public String getUrl() {
        return url;
    }

    @GraphQLField
    @GraphQLDescription("the url description")
    public String getDescription() {
        return description;
    }
}

I'm able to query the "allLinks" with this:

{
  allLinks{
    description
    url
  }
}

Works well. But I'm absolutely unable to query for "allLinks2".

Query:

{
  allLinks2(val: "abc"){
    description
    url
  }
}

I get:

{
  "data": {
    "allLinks2": null
  },
  "errors": [
    {
      "message": "Exception while fetching data (/allLinks2) : Cannot invoke \"Object.getClass()\" because \"obj\" is null",
      "path": [
        "allLinks2"
      ],
      "exception": {
        "cause": null,
        "stackTrace": [
          {
            "classLoaderName": null,
            "moduleName": "java.base",
            "moduleVersion": "17-ea",
            "methodName": "invoke",
            "fileName": "Method.java",
            "lineNumber": 561,
            "nativeMethod": false,
            "className": "java.lang.reflect.Method"
          },
          {
            "classLoaderName": "app",
            "moduleName": null,
            "moduleVersion": null,
            "methodName": "get",
            "fileName": "MethodDataFetcher.java",
            "lineNumber": 88,
            "nativeMethod": false,
            "className": "graphql.annotations.dataFetchers.MethodDataFetcher"
          },
          {
            "classLoaderName": "app",
            "moduleName": null,
            "moduleVersion": null,
            "methodName": "fetchField",
            "fileName": "ExecutionStrategy.java",
            "lineNumber": 270,
            "nativeMethod": false,
            "className": "graphql.execution.ExecutionStrategy"
          },
 [...shorted output...]

Looks like the object required by reflection mechanism to do the actual method invocation is null... but why? It works with the field .. but not with the method...

Any ideas?

br,
Alex

commented

Did some debugging...

I stumbled upon this line: https://github.com/Enigmatis/graphql-java-annotations/blob/master/src/main/java/graphql/annotations/dataFetchers/MethodDataFetcher.java#L75

The 2nd argument of newInstance is taking parameters required to call the object-class instructor. But why is "environment.getSource()" passed as arguments? I found this is null in my case.

Looks like there is a null-check missing? But I'm curious about the sense behind "source"... Can someone explain?

[update]

Okay, found the sense behind source here: https://github.com/graphql-java/graphql-java/blob/master/src/main/java/graphql/schema/DataFetchingEnvironment.java#L41

But: Why is it null in my case? What am I doing wrong? Is it really that complicated?!

commented

Hmm, some more code reading lead me to adding @GraphQLInvokeDetached ...

    @GraphQLField
    @GraphQLInvokeDetached
    public List<Link> allLinks2(DataFetchingEnvironment env, @GraphQLName("val") String value) {
        System.out.println("dfe: " + env);
        return DummyDatabase.getINSTANCE().links;
    }

Now it works. BUT:

  1. What is GraphQLInvokeDetached exactly? There's no javadoc available and no further comment...
  2. Will there be additional impacts on using this?
commented

This is getting weird...

https://github.com/Enigmatis/graphql-java-annotations#data-fetching-with-extensions

Is my simple Query class already an extension?

commented

When I make the method static, it works as well. So for now, blocker is gone.