GraphQL Apollo Federation-JVM 中 @extends 类型的解析器问题

Posted

技术标签:

【中文标题】GraphQL Apollo Federation-JVM 中 @extends 类型的解析器问题【英文标题】:Resolver Issue for @extends Type in GraphQL Apollo Federation-JVM 【发布时间】:2020-05-12 13:33:35 【问题描述】:

我对 Apollo Federation 和 Gateway 还很陌生,并尝试将 apollo federation-jvm 用于演示项目。我使用联合 jvm 创建了两个联合服务。这两项服务都通过 Apollo Gateway 相互连接。使用来自官方 github 页面的 this 节点网关示例。

以下是这些服务的架构和解析器:

联合服务 1:

video.graphql

type Video @key(fields: "videoId") 
    videoId: String!
    description: String
    relatedNameId: String


type Query 
    topVideo: Video
    allVideos: [Video]

video.graphql 的解析器

@Service
public class VideoQuery implements GraphQLQueryResolver 

    private static final List<Video> videos = Lists.newArrayList(
            Video.builder().videoId("vi00000001").description("Video 1").relatedNameId("nm000001").build(),
            Video.builder().videoId("vi00000002").description("Video 2").relatedNameId("nm000001").build()
    );

    public Video topVideo() 
        return videos.get(0);
    

    public List<Video> allVideos() 
        return videos;
    

联合服务 2:

name.graphql

type Name @key(fields: "nameId") 
    nameId: String!
    displayName: String


type Query 
    getByNameId(nameId: String): Name
    getAllNames: [Name]

name.graphql 的解析器

@Service
public class NameQuery implements GraphQLQueryResolver 

    private static final List<Name> names = Lists.newArrayList(
            Name.builder().nameId("nm0000001").displayName("Pam Beesley").build(),
            Name.builder().nameId("nm0000002").displayName("Dwight Schrute").build(),
            Name.builder().nameId("nm0000003").displayName("Michael Scott").build()
    );

    public Name getByNameId(final String nameId) 
        final Optional<Name> oName = names.stream().filter(name -> name.getNameId().equalsIgnoreCase(nameId))
                                     .findFirst();
        return oName.orElse(null);
    

    public List<Name> getAllNames(final DataFetchingEnvironment dataFetchingEnvironment) 
        return names;
    


我能够通过网关在两种服务的类型查询中调用所有 API(topVideo、allVideos、getByNameId、getAllNames),没有任何问题。

但是,当我通过将以下内容添加到 video.graphql 架构中来扩展 Name 键入 Video 类型架构时

type Name @key(fields: "nameId") @extends 
    nameId: String! @external
    getVideoByNameId: [Video]

我不确定如何为 getVideoByNameId 字段编写解析器。

我尝试将 getVideoByNameId(String nameId) 方法添加到 VideoQuery.java(从 getVideoByNameId 方法返回硬编码视频对象),但图表始终返回 null。

我还尝试使用下面的代码创建 RuntimeWiring,然后在创建 GraphQLSchema 对象时传递它,如他们github page 上的示例所示。

private static RuntimeWiring getRuntimeWiring()
        return RuntimeWiring.newRuntimeWiring()
                            .type(newTypeWiring("Name")
                                                  .dataFetcher("getVideoByNameId", new StaticDataFetcher(someVideo)))
                            .type(newTypeWiring("Query")
                                                  .dataFetcher("topVideo", new StaticDataFetcher(someVideo)))
                            .type(newTypeWiring("Query")
                                                  .dataFetcher("allVideos", new StaticDataFetcher(someVideo)))
                            .build();
    

似乎没有任何效果。非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

您需要为您的Name 类型实现fetchEntitiesresolveEntityType,与实现here 的方式类似。

【讨论】:

以上是关于GraphQL Apollo Federation-JVM 中 @extends 类型的解析器问题的主要内容,如果未能解决你的问题,请参考以下文章

Graphql Apollo Federation - 基于实现服务解析计算域

如何将 REST API 迁移到 GraphQL Apollo Federation

GraphQL Apollo Federation-JVM 中 @extends 类型的解析器问题

@apollo/federation 包的替代品

在 Apollo GraphQl Federation 中,如何在没有 @external 指令的情况下应用 @requires 逻辑?

使用和组合另一个公共 apollo graphql api 的最佳方式:federation v 模式拼接