【问题标题】:Spring Boot GraphQL can't load schemaSpring Boot GraphQL 无法加载架构
【发布时间】:2019-07-20 13:57:30
【问题描述】:

我在 Spring Boot 2+ 和 GraphQL 中使用以下示例,但在加载 graphiql 时出现以下错误,架构未加载。

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

代码通过来自邮递员但来自 Graphiql 的 POST 调用运行。

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

【问题讨论】:

  • 在我的回答中添加了更多详细信息

标签: java spring-boot graphql graphql-java


【解决方案1】:

在 Spring Boot 2+ 中使用 GraphQL 时,无需创建 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

【讨论】:

    【解决方案2】:

    您需要使用属性 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;
    }
    

    【讨论】:

      【解决方案3】:

      首先,您使用的是一个奇怪的堆栈。虽然 graphql-java-tools 最近在 Maven 中处于 com.graphql-java groupId 下,但它实际上是一个完全独立的堆栈。较新的版本在新的 groupId com.graphql-java-kickstart 下发布,以避免将来混淆。

      现在,如果您已经在使用 graphql-java-tools,那么您需要的 Starter 是 com.graphql-java-kickstart:graphql-spring-boot-starter,因为它们打算一起使用。

      您使用的启动器 (com.graphql-java:graphql-spring-boot-starter) 旨在与纯 graphql-java 一起使用。你只需要连接一个GraphQL 类型的bean。详情请见the official tutorial

      他们可以一起工作,请注意,这只是一个次优组合。

      现在,您收到此错误的原因是您的 HTTP 端点(Spring 控制器)不符合 GraphQL-over-HTTP specification,而 GraphiQL 预计会这样做(具体来说,GraphiQL 使用的是 POST variety)。邮递员不是,所以它通过了。

      将后端更改为期望请求中的 JSON 对象的最佳方法,具有以下形状:

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

      【讨论】:

        猜你喜欢
        • 2020-02-22
        • 2020-05-11
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        • 2017-11-11
        • 1970-01-01
        • 2018-02-12
        • 2017-07-13
        相关资源
        最近更新 更多