1

我正在尝试使用 GraphQL Java Annotations 创建递归模式,但会引发异常。

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());
  }
}

解析类可以正常进行,但创建模式会引发以下异常(这一行:)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)

4

1 回答 1

1

我相信这是一个已经关闭的 graphql-java-annotation 错误。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());
}

请注意,我child从 中删除了该属性TestObject,因为它并没有真正被使用(因为它被不同的提取器替换)。尽管如此,如果您不理会它,也不会有任何区别 - 自定义提取器(嵌套 via @GraphQLContext)仍然会覆盖它。背后的想法@GraphQLContext是允许嵌套查询,而不必将逻辑塞入模型中,甚至不必接触模型对象。

如果要重命名字段或添加描述,也可以对字段进行注释,例如

@GraphQLQuery(name = "child", description = "The child object")
public TestObject getChild() {
    return child;
}
于 2017-06-15T15:44:19.320 回答