SpringBoot + WebFlux + GraphQL -源对象应为“com.example.MyObject”的示例,但得到的却是“reactor.core.publisher.FluxJust”

bmp9r5qi  于 2022-11-23  发布在  Spring
关注(0)|答案(1)|浏览(316)

bounty将在6天后过期。回答此问题可获得+50的声望奖励。k-wasilewski正在寻找标准答案

我正在尝试对Spring+MongoDB+GraphQL应用程序实现一个React式架构,我已经学习了一些相关教程,但是每当我从GraphQLQueryResolver返回一个Publisher<Page>时,我就会收到这个错误:

2022-11-17 09:18:56.316 ERROR 14166 --- [nio-8081-exec-1] 
g.servlet.DefaultGraphQLErrorHandler     : Error executing query 
(ExceptionWhileDataFetching): Exception while fetching data (/getPages/id) : Expected 
source object to be an instance of 'com.example.jobscraperspringserver.types.Page' but 
instead got 'reactor.core.publisher.FluxJust'

我已经处理了返回的对象(尝试了Flux<Page>Publisher<List<Page>>和其他配置)以及schema.graphqls中的一个类型,但它们都不起作用。此外,这是在大多数教程以及其他一些SO问题中应该起作用的,所以我想这要么是我代码中的某个bug,要么是体系结构的缺陷(例如,某个不支持类型转换的错误依赖项)。
下面是我的代码:

页面查询.java

@Component
public class PageQuery implements GraphQLQueryResolver {
    @Autowired
    PageService pageService;

    public Publisher<Page> getPages() {
        return pageService.getPages();
    }
}

页面服务.java

@Service
public class PageService {

    public Flux<Page> getPages() {
        return Flux.just(new Page(12));
    }

}

架构.图形

type Page {
    id: Int!
    host: String
}

type Query {
    getPages: Page
}

pom.xml文件

...

<dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 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>
        <!-- GraphQL subscriptions -->
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
        </dependency>
        <!-- MongoDB -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
            <version>2.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-reactivestreams</artifactId>
        </dependency>
        <!-- h2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- JWT -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <!-- WebFlux -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
            <version>2.6.4</version>
        </dependency>
    </dependencies>

...

更新

显然com.graphql-java不能处理WebFlux,所以我替换了

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

<dependency>
  <groupId>org.springframework.experimental</groupId>
  <artifactId>graphql-spring-boot-starter</artifactId>
  <version>1.0.0-M3</version>
</dependency>

但是现在我得到的是null而不是Page

更新2我还尝试了

<dependency>
  <groupId>com.graphql-java-kickstart</groupId>
  <artifactId>graphql-spring-boot-starter</artifactId>
  <version>11.1.0</version>
</dependency>
<dependency>
  <groupId>com.graphql-java-kickstart</groupId>
  <artifactId>graphql-kickstart-spring-webflux</artifactId>
  <version>11.1.0</version>
</dependency>

但是得到了相同的结果。我认为它支持CompletableFuture<List<Page>>,但是这仍然是阻塞的,我看过很多关于从graphql解析器返回Mono/Flux的教程...

UPDATE 3我已经将所有Spring模块的版本更新为2.6.3以保持一致,并且我还删除了spring-boot-starter-web依赖项,因为spring-boot-starter-webflux应该足够了;但是这些修复都没有解决我的问题。

avkwfej4

avkwfej41#

首先,如果你使用的是Sping Boot ,我建议你使用spring-boot-starter-graphql而不是graphql-spring-boot-starter,并且你需要添加spring-boot-starter-webflux来实现React式数据获取器。另外,如果你想返回Flux,你应该在模式中将返回类型定义为数组(例如getPages: [Page!]!),否则,你应该返回Mono
这将允许您按如下方式实现查询:

@Controller
public class PageController {

    // ...
    
    @QueryMapping 
    public Flux<Page> getPages() {
        return pageService.getPages();
    }
}

但是您应该注意到,默认情况下,MonoFlux被调整为CompletableFuture,其中Flux值被聚合并转换为List。如果您希望对响应进行流处理,那么您还应该使用GraphQL订阅而不是查询。

相关问题