Graphql 联合在扩展关系上返回 null
Posted
技术标签:
【中文标题】Graphql 联合在扩展关系上返回 null【英文标题】:Graphql federation returning null on extended relation 【发布时间】:2020-09-09 14:34:25 【问题描述】:我正在尝试设置一个原型,以便在多个 java 微服务中使用 graphql,这需要我将多个 graphql 模式合并为一个。
我正在使用 2 个 java 服务和带有 ApolloGateway 的 ApolloServer;它在操场上显示了以下架构:
type Client
id: ID!
name: String
linkeduser: User
type Query
user(id: ID!): User
users: [User]
client(id: ID!): Client
clients: [Client]
type User
id: ID!
name: String
运行简单查询时:
query client
client(id: 1)
id
name
linkeduser
id
name
我希望返回的是一个带有linkeduser 的客户端;调试时客户端服务被查询,用户服务被查询,但响应是:
"data":
"client":
"id": "1",
"name": "Bob",
"linkeduser": null
如何在我的客户端中获得链接的用户响应?
我尝试返回用户列表、带有链接用户列表的新客户端对象、单个用户。 https://github.com/apollographql/federation-jvm 的例子是这段代码的基础,虽然我还没有看到它工作。
代码:
服务 1:客户端
@WebServlet(loadOnStartup = 1, urlPatterns = "/graphql")
public class GraphQLService extends GraphQLHttpServlet
@Override
protected GraphQLConfiguration getConfiguration()
return GraphQLConfiguration.with(getGraphQLSchema()).build();
private static GraphQLSchema getGraphQLSchema()
InputStream inputStream = client.GraphQLService.class
.getClassLoader().getResourceAsStream("schema.graphqls");
TypeDefinitionRegistry parse = new SchemaParser().parse(inputStream);
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Query", builder -> builder.defaultDataFetcher(GraphQLService::getClient))
.build();
return com.apollographql.federation.graphqljava.Federation.transform(parse, runtimeWiring)
.fetchEntities(env -> env.<List<Map<String, Object>>>getArgument(_Entity.argumentName)
.stream()
.map(values ->
if ("Client".equals(values.get("__typename")))
final Object id = values.get("id");
if (id instanceof String)
return getSingleClient((String) id);
return null;
)
.collect(Collectors.toList()))
.resolveEntityType(env ->
final Object src = env.getObject();
if (src instanceof Client)
return env.getSchema().getObjectType("Client");
return null;
).build();
private static Object getClient(DataFetchingEnvironment environment)
switch (environment.getFieldDefinition().getName())
case "client":
return getSingleClient(environment.getArgument("id"));
case "clients":
return getAllClients();
default:
return null;
//... extra code with simple getters
使用此架构:
extend type Query
client(id: ID!): Client
clients: [Client]
type Client @key(fields: "id")
id: ID!
name: String
服务 2:用户
@WebServlet(loadOnStartup = 1, urlPatterns = "/graphql")
public class GraphQLService extends GraphQLHttpServlet
@Override
protected GraphQLConfiguration getConfiguration()
return GraphQLConfiguration.with(getGraphQLSchema()).build();
private static GraphQLSchema getGraphQLSchema()
InputStream inputStream = user.GraphQLService.class
.getClassLoader().getResourceAsStream("schema.graphqls");
TypeDefinitionRegistry parse = new SchemaParser().parse(inputStream);
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Query", builder -> builder.defaultDataFetcher(GraphQLService::getUser))
.build();
return com.apollographql.federation.graphqljava.Federation.transform(parse, runtimeWiring)
.fetchEntities(env -> env.<List<Map<String, Object>>>getArgument(_Entity.argumentName)
.stream()
.map(values ->
if ("Client".equals(values.get("__typename")))
final Object id = values.get("id");
if (id instanceof String)
return getSingleUser((String) id);
return null;
)
.collect(Collectors.toList()))
.resolveEntityType(env ->
final Object src = env.getObject();
if (src instanceof User)
return env.getSchema().getObjectType("User");
return null;
)
.build();
private static Object getUser(DataFetchingEnvironment environment)
switch (environment.getFieldDefinition().getName())
case "user":
return getSingleUser(environment.getArgument("id"));
case "users":
return getAllUsers();
default:
return null;
//... extra code with simple getters
使用此架构:
type Query @extends
user (id: ID!): User
users: [User]
type User @key(fields: "id")
id: ID!
name: String
type Client @key(fields: "id") @extends
id: ID! @external
linkeduser : User
POM.xml 中的版本
<graphql.version>14.0</graphql.version>
<graphql-tools.version>5.2.4</graphql-tools.version>
<graphql-servlet.version>9.0.1</graphql-servlet.version>
<graphql-federation-support.version>0.4.0</graphql-federation-support.version>
【问题讨论】:
【参考方案1】:在用户服务中,您需要返回一个客户端类型的 pojo,并带有一个用于链接用户的 getter(仅需要存在扩展字段):
if ("Client".equals(values.get("__typename")))
final Object id = values.get("id");
if (id instanceof String)
return new Client((String) id, getSingleUser((String) id));
resolveTypeEntity 也需要解析到所述客户端
【讨论】:
以上是关于Graphql 联合在扩展关系上返回 null的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Apollo/GraphQL 返回一个不可扩展的对象?