GraphQL Java 注释递归问题
GraphQL Java Annotations recursion issue
我正在尝试使用 GraphQL Java 注释创建递归模式,但抛出了异常。
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.ThreadLocalRandom;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.annotations.GraphQLAnnotations;
import graphql.annotations.GraphQLDataFetcher;
import graphql.annotations.GraphQLDescription;
import graphql.annotations.GraphQLField;
import graphql.annotations.GraphQLName;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
public class RecursiveSchemaTest {
@GraphQLDescription("TestObject object")
@GraphQLName("TestObject")
public static class TestObject {
@GraphQLField
private Integer id;
@GraphQLField
@GraphQLDataFetcher(TestObjectDataFetcher.class)
private TestObject child;
public TestObject(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public TestObject getChild() {
return child;
}
public void setChild(TestObject child) {
this.child = child;
}
}
public static class TestObjectDataFetcher implements DataFetcher<TestObject> {
@Override
public TestObject get(DataFetchingEnvironment environment) {
return new TestObject(ThreadLocalRandom.current().nextInt());
}
}
@Test
public void test() {
GraphQLObjectType graphQLObjectType = GraphQLAnnotations.object(TestObject.class);
GraphQLObjectType rootQuery = GraphQLObjectType.newObject().name("data").field(
newFieldDefinition().name(graphQLObjectType.getName()).type(graphQLObjectType)
.dataFetcher(new TestObjectDataFetcher()).build()).build();
GraphQLSchema schema = GraphQLSchema.newSchema().query(rootQuery).build();
GraphQL graphQL = GraphQL.newGraphQL(schema).build();
ExecutionResult result = graphQL.execute("{ TestObject { id, child { id , child { id }}");
Assert.assertFalse(result.getErrors() != null && !result.getErrors().isEmpty());
Assert.assertNotNull(result.getData());
}
}
解析 class 正常,但创建架构会抛出以下异常(这一行:GraphQLSchema schema = GraphQLSchema.newSchema().query(rootQuery).build();
):
graphql.AssertException: All types within a GraphQL schema must have unique names. No two provided types may have the same name.
No provided type may have a name which conflicts with any built in types (including Scalar and Introspection types).
You have redefined the type 'TestObject' from being a 'GraphQLObjectTypeWrapper' to a 'GraphQLObjectTypeWrapper'
at graphql.schema.SchemaUtil.assertTypeUniqueness(SchemaUtil.java:86)
at graphql.schema.SchemaUtil.collectTypesForObjects(SchemaUtil.java:122)
at graphql.schema.SchemaUtil.collectTypes(SchemaUtil.java:56)
at graphql.schema.SchemaUtil.collectTypesForObjects(SchemaUtil.java:128)
at graphql.schema.SchemaUtil.collectTypes(SchemaUtil.java:56)
at graphql.schema.SchemaUtil.collectTypesForObjects(SchemaUtil.java:128)
at graphql.schema.SchemaUtil.collectTypes(SchemaUtil.java:56)
at graphql.schema.SchemaUtil.allTypes(SchemaUtil.java:153)
at graphql.schema.GraphQLSchema.<init>(GraphQLSchema.java:42)
at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:130)
at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:125)
at RecursiveSchemaTest.test(RecursiveSchemaTest.java:74)
知道为什么没有正确创建模式吗?我正在使用 graphql-java (3.0.0) 和 graphql-java-annotations (0.14.0)
的最新版本
我认为这是 graphql-java-注释 has already been closed 的错误。以前版本的 graphql-java 允许重复类型名称,但从 3.0.0 开始是错误的,注解库还没有跟上。
修复应该在即将发布的版本中...
顺便说一句,查看我的库,graphql-spqr,它允许更加自动化的架构生成,并且可以轻松涵盖您的用例:
public static class TestObject {
private Integer id;
public TestObject(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
public static class TestObjectService {
@GraphQLQuery(name = "TestObject")
public TestObject getRoot() { //no GraphQL-specific classes mentioned
return getRandom();
}
@GraphQLQuery(name = "child")
public TestObject getChild(@GraphQLContext TestObject parent) {
return getRandom();
}
private TestObject getRandom() {
return new TestObject(ThreadLocalRandom.current().nextInt());
}
}
@Test
public void test() {
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withOperationsFromSingleton(new TestObjectService())
.generate(); //that's all :)
GraphQL graphQL = GraphQL.newGraphQL(schema).build();
ExecutionResult result = graphQL.execute("{ TestObject { id, child { id , child { id }}}}"); //your query has a syntax error
assertFalse(result.getErrors() != null && !result.getErrors().isEmpty());
assertNotNull(result.getData());
}
请注意,我从 TestObject
中删除了 child
属性,因为它并没有真正被使用(因为它被不同的提取器取代)。尽管如此,如果你不去理会它,也不会有什么不同——自定义获取器(通过 @GraphQLContext
嵌套)仍然会覆盖它。 @GraphQLContext
背后的想法是允许嵌套查询,而不必将逻辑塞进模型中,甚至不必触及模型对象。
如果您想重命名字段或添加说明,也可以对字段进行注释,例如
@GraphQLQuery(name = "child", description = "The child object")
public TestObject getChild() {
return child;
}
我正在尝试使用 GraphQL Java 注释创建递归模式,但抛出了异常。
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.ThreadLocalRandom;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.annotations.GraphQLAnnotations;
import graphql.annotations.GraphQLDataFetcher;
import graphql.annotations.GraphQLDescription;
import graphql.annotations.GraphQLField;
import graphql.annotations.GraphQLName;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
public class RecursiveSchemaTest {
@GraphQLDescription("TestObject object")
@GraphQLName("TestObject")
public static class TestObject {
@GraphQLField
private Integer id;
@GraphQLField
@GraphQLDataFetcher(TestObjectDataFetcher.class)
private TestObject child;
public TestObject(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public TestObject getChild() {
return child;
}
public void setChild(TestObject child) {
this.child = child;
}
}
public static class TestObjectDataFetcher implements DataFetcher<TestObject> {
@Override
public TestObject get(DataFetchingEnvironment environment) {
return new TestObject(ThreadLocalRandom.current().nextInt());
}
}
@Test
public void test() {
GraphQLObjectType graphQLObjectType = GraphQLAnnotations.object(TestObject.class);
GraphQLObjectType rootQuery = GraphQLObjectType.newObject().name("data").field(
newFieldDefinition().name(graphQLObjectType.getName()).type(graphQLObjectType)
.dataFetcher(new TestObjectDataFetcher()).build()).build();
GraphQLSchema schema = GraphQLSchema.newSchema().query(rootQuery).build();
GraphQL graphQL = GraphQL.newGraphQL(schema).build();
ExecutionResult result = graphQL.execute("{ TestObject { id, child { id , child { id }}");
Assert.assertFalse(result.getErrors() != null && !result.getErrors().isEmpty());
Assert.assertNotNull(result.getData());
}
}
解析 class 正常,但创建架构会抛出以下异常(这一行:GraphQLSchema schema = GraphQLSchema.newSchema().query(rootQuery).build();
):
graphql.AssertException: All types within a GraphQL schema must have unique names. No two provided types may have the same name.
No provided type may have a name which conflicts with any built in types (including Scalar and Introspection types).
You have redefined the type 'TestObject' from being a 'GraphQLObjectTypeWrapper' to a 'GraphQLObjectTypeWrapper'
at graphql.schema.SchemaUtil.assertTypeUniqueness(SchemaUtil.java:86)
at graphql.schema.SchemaUtil.collectTypesForObjects(SchemaUtil.java:122)
at graphql.schema.SchemaUtil.collectTypes(SchemaUtil.java:56)
at graphql.schema.SchemaUtil.collectTypesForObjects(SchemaUtil.java:128)
at graphql.schema.SchemaUtil.collectTypes(SchemaUtil.java:56)
at graphql.schema.SchemaUtil.collectTypesForObjects(SchemaUtil.java:128)
at graphql.schema.SchemaUtil.collectTypes(SchemaUtil.java:56)
at graphql.schema.SchemaUtil.allTypes(SchemaUtil.java:153)
at graphql.schema.GraphQLSchema.<init>(GraphQLSchema.java:42)
at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:130)
at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:125)
at RecursiveSchemaTest.test(RecursiveSchemaTest.java:74)
知道为什么没有正确创建模式吗?我正在使用 graphql-java (3.0.0) 和 graphql-java-annotations (0.14.0)
的最新版本我认为这是 graphql-java-注释 has already been closed 的错误。以前版本的 graphql-java 允许重复类型名称,但从 3.0.0 开始是错误的,注解库还没有跟上。
修复应该在即将发布的版本中...
顺便说一句,查看我的库,graphql-spqr,它允许更加自动化的架构生成,并且可以轻松涵盖您的用例:
public static class TestObject {
private Integer id;
public TestObject(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
public static class TestObjectService {
@GraphQLQuery(name = "TestObject")
public TestObject getRoot() { //no GraphQL-specific classes mentioned
return getRandom();
}
@GraphQLQuery(name = "child")
public TestObject getChild(@GraphQLContext TestObject parent) {
return getRandom();
}
private TestObject getRandom() {
return new TestObject(ThreadLocalRandom.current().nextInt());
}
}
@Test
public void test() {
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withOperationsFromSingleton(new TestObjectService())
.generate(); //that's all :)
GraphQL graphQL = GraphQL.newGraphQL(schema).build();
ExecutionResult result = graphQL.execute("{ TestObject { id, child { id , child { id }}}}"); //your query has a syntax error
assertFalse(result.getErrors() != null && !result.getErrors().isEmpty());
assertNotNull(result.getData());
}
请注意,我从 TestObject
中删除了 child
属性,因为它并没有真正被使用(因为它被不同的提取器取代)。尽管如此,如果你不去理会它,也不会有什么不同——自定义获取器(通过 @GraphQLContext
嵌套)仍然会覆盖它。 @GraphQLContext
背后的想法是允许嵌套查询,而不必将逻辑塞进模型中,甚至不必触及模型对象。
如果您想重命名字段或添加说明,也可以对字段进行注释,例如
@GraphQLQuery(name = "child", description = "The child object")
public TestObject getChild() {
return child;
}