如何使用graphql-java和graphql-java-servlet为GraphQL订阅编写解析器?

时间:2019-02-20 19:18:01

标签: java spring spring-boot graphql

我尝试设置基于Spring Boot的GraphQL服务(基于项目graphql-spring-boot-starterhttps://github.com/graphql-java-kickstart/graphql-spring-boot),该服务不使用graphql-java-tools,但是构建了手动/编程运行时接线。 GraphQL查询和变异就可以很好地工作。但是,我无法使订阅生效。

我添加了以下连线以绑定用于订阅的DataFetcher:

RuntimeWiring.Builder runtimeWiringBuilder =
    newRuntimeWiring()
    ...
        .type(TypeRuntimeWiring.newTypeWiring("Subscription")
            .dataFetcher("stockQuotes", gqlService::stockQuotes)
        );

我的解析器函数正确返回一个org.reactivestream.Publisher

Publisher<StockPriceUpdate> stockQuotes(DataFetchingEnvironment env) {
    return stockTickerPublisher.getPublisher();
}

但是,如果我从GraphiQL或GraphQL Playground调用订阅,则会出现以下错误: “没有为类graphql.execution.reactive.CompletionStageMappingPublisher找到序列化程序”(下面的堆栈跟踪)。

似乎来自库GraphQLObjectMapper的{​​{1}}试图将结果(包装的graphql-java-servlet)直接序列化为JSON结果。当然,那没有道理。相反,每当发布者发出下一个更新时,它都应作为发布者的侦听器并通过WebSocket推送更新。

据我了解,org.reactivestream.Publisher已经内置了对通过WebSockets进行订阅的支持。不幸的是,没有可用的普通示例,该示例无需使用graphql-tools 即可订阅

有什么想法可以使它正常工作吗?非常感谢!

我的graphql-java-servlet文件的相关部分是:

application.yml

模式(节选):

server:
  port: 9200

graphql:
  servlet:
    mapping: /graphql
    enabled: true
    corsEnabled: true
    websocket:
      enabled: true
      path: /graphql
    subscriptions:
      websocket:
        path: /graphql

堆栈跟踪:

schema {
  query: Query
  mutation: Mutation
  subscription : Subscription
}

type Subscription {
  stockQuotes: StockPriceUpdate!
}

type StockPriceUpdate {
  dateTime : String
  stockCode : String
  stockPrice : Float
  stockPriceChange : Float
}

1 个答案:

答案 0 :(得分:1)

当您尝试使用自2018年3月22日(v.0.7.2)以来未更新的基于电子的GraphiQL.app时,就会出现堆栈上方的痕迹。因此,要解决问题并查看订阅是否有效:

  1. 请勿使用GraphiQL.app;

  2. 向您的pom.xml添加以下依赖项,以从Spring Boot Micro Service中暴露已重发的/graphiql端点(用于测试):

        <!-- Graph(i)QL tool: for development -->
        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>5.4.1</version>
        </dependency>
    默认情况下,
  1. graphiql期望订阅通过/subscriptions端点公开。所以:

    • graphql.subscriptions.websocket.path/graphql更改为/subscriptions

    • 或在graphiql中自定义application.yml(以反映graphql的配置):

graphiql:
  endpoint:
    subscriptions: /graphql

重新启动后,您可以转到http://localhost:9200/graphiql并运行订阅,如下所示:

subscription StockCodeSubscription {
    stockQuotes {
        dateTime
        stockCode
        stockPrice
        stockPriceChange
    }
}

应该工作!