question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

DataFetcherResult support to return data & errors

See original GitHub issue

DataFetcherResult was introduced in the graphql-java v7.0 to allow returning a wrapper object which will contain the data the resolver is supposed to return + a list of errors.

I took the sample project to try:

    @GraphQLMutation(name = "createVendor")
    public DataFetcherResult<Vendor> createVendor(@GraphQLArgument(name = "vendor") Vendor vendor){
        Vendor createdVendor =  new Vendor((long) mockVendorStorage.size() + 1,
                vendor.getName(),
                vendor.getAddress());
        mockVendorStorage.add(createdVendor);
        List<GraphQLError> errors = new ArrayList<>();
        errors.add(new GenericGraphQLError("invalid data"));
        return new DataFetcherResult<>(createdVendor, errors);
    }

Then I invoke the method:

mutation {
  createVendor(
    vendor: {
      id: 1
      name: "hello"
      address: {
        city: "mtl"
        postalCode:"h2c1f1"
        streetAndNumber: "123 asd"
      }
      productsInStock:[
        {
          stockSize: 1
          product:{
            id: 1
            name: "aaa"
            description:"asdas"
          }
        }
      ]
    }) {
    id
    name
  }
}

Instead of returning the data + the error, it’s just failing because spqr hasn’t extracted the data part from the DataFetcherResult:

{
  "data": null,
  "errors": [
    {
      "message": "Validation error of type FieldUndefined: Field 'id' in type 'DataFetcherResult_Vendor' is undefined",
      "locations": [
        {
          "line": 36,
          "column": 5
        }
      ],
      "description": "Field 'id' in type 'DataFetcherResult_Vendor' is undefined",
      "validationErrorType": "FieldUndefined",
      "errorType": "ValidationError",
      "path": null,
      "extensions": null
    },
    {
      "message": "Validation error of type FieldUndefined: Field 'name' in type 'DataFetcherResult_Vendor' is undefined",
      "locations": [
        {
          "line": 37,
          "column": 5
        }
      ],
      "description": "Field 'name' in type 'DataFetcherResult_Vendor' is undefined",
      "validationErrorType": "FieldUndefined",
      "errorType": "ValidationError",
      "path": null,
      "extensions": null
    }
  ],
  "extensions": null
}

Are you planning to support this new feature from graphql-java implementation, since actually it was a big missing peace from the GraphQL spec.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
kaqqaocommented, Mar 5, 2018

Glad we got it sorted out! Cheers! 🍻

0reactions
elenigencommented, Mar 5, 2018

I was right, the source of the problem is from graphql-java and it was already fixed (#888), so it would be part of the next release.

As reference, here’s what I did to make it work:

Code

    @GraphQLMutation(name = "createVendor")
    public DataFetcherResult<Vendor> createVendor(@GraphQLArgument(name = "vendor") Vendor vendor){
        Vendor createdVendor =  new Vendor((long) mockVendorStorage.size() + 1,
                vendor.getName(),
                vendor.getAddress());
        mockVendorStorage.add(createdVendor);
        List<GraphQLError> errors = new ArrayList<>();
        errors.add(generateFakeError("invalid data1", "path1"));
        errors.add(generateFakeError("invalid data2", "path1"));
        return new DataFetcherResult<>(createdVendor, errors);
    }

    private GraphQLError generateFakeError(String message, String path) {
        return new GraphQLError() {
            @Override
            public String getMessage() {
                return "Something went wrong";
            }

            @Override
            public List<Object> getPath() {
                return Collections.singletonList(path);
            }

            @Override
            public List<SourceLocation> getLocations() {
                return null;
            }

            @Override
            public ErrorType getErrorType() {
                return ErrorType.ValidationError;
            }
        };
    }

Request

mutation {
  createVendor(
    vendor: {
      id: 1
      name: "hello"
      address: {
        city: "mtl"
        postalCode:"h2c1f1"
        streetAndNumber: "123 asd"
      }
      productsInStock:[
        {
          stockSize: 1
          product:{
            id: 1
            name: "aaa"
            description:"asdas"
          }
        }
      ]
    }) {
    id
    name
  }
}

Response

{
  "data": {
    "createVendor": {
      "id": 1,
      "name": "hello"
    }
  },
  "errors": [
    {
      "message": "invalid data1",
      "path": [
        "createVendor",
        "path1"
      ]
    },
    {
      "message": "invalid data2",
      "path": [
        "createVendor",
        "path2"
      ]
    }
  ]
}

Finally, I was able to make it work, thanks a lot for your help! 😃 🍻 🌴

Read more comments on GitHub >

github_iconTop Results From Across the Web

DataFetcherResult (graphql-java 12.0 API) - javadoc.io
An object that can be returned from a DataFetcher that contains both data, local context and errors to be relativized and added to...
Read more >
Spring Boot GraphQL Tutorial #10 - Returning data and errors
It is possible to return both data and multiple errors in a graphql resolver by returning a graphql.execution. DataFetcherResult either ...
Read more >
Execution - GraphQL Java
In this example, the DataFetcher retrieves a user from another GraphQL resource and returns its data and errors. DataFetcher userDataFetcher = new DataFetcher() ......
Read more >
graphql.execution.DataFetcherResult java code examples
public DataFetcherResult build() { return new DataFetcherResult<>(data, errors, localContext);
Read more >
graphql.execution.DataFetcherResult Java Examples
getData(), element, type); return (S) DataFetcherResult.newResult() .data(convertedData) .errors(result.getErrors()) .localContext(result.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found