4

I am using the following example with Spring Boot 2+ and GraphQL but I am getting the error below when loading graphiql, the schema doesn't load.

https://github.com/TechPrimers/spring-boot-graphql-query-example

The code works through a POST call from postman but from Graphiql.

@RestController
public class GraphQLController {

    private GraphQLService graphQLService;

    public GraphQLController(GraphQLService graphQLService) {
        this.graphQLService = graphQLService;
    }

    @PostMapping("/graphql")
    public ExecutionResult graphQl(@RequestBody String query) {
        ExecutionResult result = graphQLService.getGraphQL().execute(query);
        return result;
    }
}

{
  "data": null,
  "errors": [
    {
      "message": "Invalid Syntax : offending token '\"query\"' at line 1 column 1",
      "sourcePreview": "{\"query\":\"\\n  query IntrospectionQuery {\\n    __schema {\\n      queryType { name }\\n      mutationType { name }\\n      types {\\n        ...FullType\\n      }\\n      directives {\\n        name\\n        description\\n        locations\\n        args {\\n          ...InputValue\\n        }\\n      }\\n    }\\n  }\\n\\n  fragment FullType on __Type {\\n    kind\\n    name\\n    description\\n    fields(includeDeprecated: true) {\\n      name\\n      description\\n      args {\\n        ...InputValue\\n      }\\n      type {\\n        ...TypeRef\\n      }\\n      isDeprecated\\n      deprecationReason\\n    }\\n    inputFields {\\n      ...InputValue\\n    }\\n    interfaces {\\n      ...TypeRef\\n    }\\n    enumValues(includeDeprecated: true) {\\n      name\\n      description\\n      isDeprecated\\n      deprecationReason\\n    }\\n    possibleTypes {\\n      ...TypeRef\\n    }\\n  }\\n\\n  fragment InputValue on __InputValue {\\n    name\\n    description\\n    type { ...TypeRef }\\n    defaultValue\\n  }\\n\\n  fragment TypeRef on __Type {\\n    kind\\n    name\\n    ofType {\\n      kind\\n      name\\n      ofType {\\n        kind\\n        name\\n        ofType {\\n          kind\\n          name\\n          ofType {\\n            kind\\n            name\\n            ofType {\\n              kind\\n              name\\n              ofType {\\n                kind\\n                name\\n                ofType {\\n                  kind\\n                  name\\n                }\\n              }\\n            }\\n          }\\n        }\\n      }\\n    }\\n  }\\n\"}\n",
      "offendingToken": "\"query\"",
      "locations": [
        {
          "line": 1,
          "column": 1,
          "sourceName": null
        }
      ],
      "errorType": "InvalidSyntax",
      "path": null,
      "extensions": null
    }
  ],
  "dataPresent": false,
  "extensions": null
}
1
  • Added more details to my answer Commented Feb 28, 2019 at 17:37

3 Answers 3

3

You need to create your own object with properties query, operationName and arg.

public class Data {
    private String query;

    public String getQuery() {
        return query;
    }

    public void setQuery(String query) {
        this.query = query;
    }
}

@PostMapping("/graphql")
public ExecutionResult graphQl(@RequestBody Data query) {
    ExecutionResult result = graphQLService.getGraphQL().execute(query.getQuery());
    return result;
}
Sign up to request clarification or add additional context in comments.

1 Comment

there are end point named ghrapql/schema.json this should genrated when I set the path graphql.servlet.mapping=/graphql graphiql.endpoint=/graphql but it loaded one time and now it now found anymore
1

First off, you're using a strange stack. While graphql-java-tools has up to recently lived under the com.graphql-java groupId in Maven, it is actually a completely separate stack. The more recent releases are published under a new groupId com.graphql-java-kickstart to avoid future confusion.

Now, if you're already using graphql-java-tools, the Starter you need is com.graphql-java-kickstart:graphql-spring-boot-starter as they're intended to be used together.

The starter you're using (com.graphql-java:graphql-spring-boot-starter) is intended to be used with pure graphql-java. You just need to wire in a bean of type GraphQL. See the official tutorial for more details.

They can be made to work together, mind you, it's just a suboptimal combo.

Now, the reason you're getting this error is that your HTTP endpoint (Spring Controller) does not comply with the GraphQL-over-HTTP specification, and GraphiQL is expecting that (specifically, GraphiQL is using the POST variety). Postman isn't, so it passes.

The best way it to change your backend to expect a JSON object in request, with the following shape:

{
  "query": "...",
  "operationName": "...",
  "variables": { "myVariable": "someValue", ... }
}

Comments

0

When using GraphQL with Spring Boot 2+, there is no need to create a POST API endpoint /graphql. Here are the steps to follow:

Step 1: Add dependencies in pom.xml for GraphQL:

        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>

Step 2: Create GraphQL schema: Here is a sample GraphQL schema:

type Employee {
  id: ID!
  name: String!
  department: String! 
  salary: Int!  
} 

type Query { 
  getEmployees: [Employee]! 
  countEmployees: Float!
  getEmployee(id: ID):Employee
} 

type Mutation { 
    newEmployee (name: String!, department: String!, salary: Int!): Employee
    deleteEmployee(id: ID): Boolean!
}

Step 3: Create GraphQL classes and mark them with the annotation @Component Here is a sample class:

@Component
public class EmployeeQuery implements GraphQLQueryResolver {

    @Autowired
    private EmployeeService employeeservice;

    public List<Employee> getEmployees() {
        return employeeservice.findAll();
    }

    public long countEmployees() {
        return employeeservice.count();
    }

    public Optional<Employee> getEmployee(final int id) {
        return employeeservice.findById(id);
    }
}

After this, the endpoint /graphql is automatically available and GraphiQL will also work without any issues. I have written a simple GraphQL and Spring Boot example in a blog post with working code in GitHub. Please refer to: http://softwaredevelopercentral.blogspot.com/2019/11/graphql-spring-boot-and-mysql-tutorial.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.