Spring Boot GraphQL не может загрузить схему

Я использую следующий пример с Spring Boot 2+ и GraphQL, но при загрузке graphiql я получаю указанную ниже ошибку, схема не загружается.

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

Код работает через POST-вызов от почтальона, но из 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
}

person Chirdeep Tomar    schedule 26.02.2019    source источник
comment
К моему ответу добавлены подробности   -  person kaqqao    schedule 28.02.2019


Ответы (3)


Вам необходимо создать свой собственный объект со свойствами query, operationName и 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;
}
person Samin Hajrulahovic    schedule 16.06.2019

Во-первых, вы используете странный стек. Хотя graphql-java-tools до недавнего времени находился под com.graphql-java groupId в Maven, на самом деле это совершенно отдельный стек. Более поздние выпуски публикуются под новым groupId com.graphql-java-kickstart, чтобы избежать путаницы в будущем.

Теперь, если вы уже используете graphql-java-tools, вам понадобится com.graphql-java-kickstart:graphql-spring-boot-starter Стартер, поскольку они предназначены для совместного использования.

Используемый вами стартер (com.graphql-java:graphql-spring-boot-starter) предназначен для использования с чистым graphql-java. Вам просто нужно подключить bean-компонент типа GraphQL. Дополнительные сведения см. В официальном руководстве.

Их можно заставить работать вместе, заметьте, это просто неоптимальная комбинация.

Теперь причина, по которой вы получаете эту ошибку, заключается в том, что ваша конечная точка HTTP (Spring Controller) не соответствует спецификация GraphQL-over-HTTP, и GraphiQL ожидает этого (в частности, GraphiQL использует POST разновидность). Почтальон нет, так что проходит.

Лучший способ изменить ваш сервер таким образом, чтобы он ожидал в запросе объект JSON, имеющий следующую форму:

{
  "query": "...",
  "operationName": "...",
  "variables": { "myVariable": "someValue", ... }
}
person kaqqao    schedule 28.02.2019

При использовании GraphQL с Spring Boot 2+ нет необходимости создавать конечную точку POST API / graphql. Вот шаги, которые нужно выполнить:

Шаг 1. Добавьте зависимости в pom.xml для 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>

Шаг 2. Создайте схему GraphQL. Вот пример схемы GraphQL:

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!
}

Шаг 3. Создайте классы GraphQL и пометьте их аннотацией @Component Вот пример класса:

@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);
    }
}

После этого конечная точка / graphql становится автоматически доступной, и GraphiQL также будет работать без каких-либо проблем. Я написал простой пример GraphQL и Spring Boot в блоге с рабочим кодом на GitHub. Пожалуйста, обратитесь к: http://softwaredevelopercentral.blogspot.com/2019/11/graphql-spring-boot-and-mysql-tutorial.html

person Aj Tech Developer    schedule 02.11.2019