ApacheCayenne类的Schema Generator

时间:2018-03-23 19:02:35

标签: java graphql-java

我正在尝试使用SPQR从Cayenne生成的类生成GraphQL架构。 Cayenne类看起来像这样

public class MyCayenneClass {
  public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
  public static final Property<Integer> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);

  public void setAProperty(Integer aProperty) {
      writeProperty("aProperty", aProperty);
  }
  public Integer getAProperty() {
      return (Integer)readProperty("aProperty");
  }

  public void setAnotherProperty(String anotherProperty) {
      writeProperty("anotherProperty", anotherProperty);
  }
  public String getAnotherProperty() {
      return (String)readProperty("anotherProperty");
  }
}

由于该类不是简单的POJO,因此SPQR会抛出异常并且不会生成架构。

Error: QUERY_ROOT fields must be an object with field names as keys or a function which returns such an object.

这里最好的方法是什么(不修改cayenne类(即注释方法)?

GraphQLEndPoing.java

@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {

public GraphQLEndpoint() {
    super(buildSchema());
}

//This method used SPQR
private static GraphQLSchema buildSchema() {
    GraphQLSchema schemaGenerator = new GraphQLSchemaGenerator()
            .withOperationsFromSingletons(myRepository) //register the beans
            .generate();
    return schemaGenerator;
}

 private static final MyRepository myRepository;

 static {
     myRepository= new MyRepository ();
 }
}

MyRepository.java

public class MyRepository{

private MyLibService libService;

 @GraphQLQuery
 public MyCayenneClass  find(Integer id) {
    List<MyCayenneClass> myList= libService.fetchById(new Integer[] {id});
    return myList.get(0);
 }
}

* FYI。如果我声明架构。代码将正常工作

schema {
  query: Query
}

type Query {
  find(id: Int): MyCayenneClass
}

type ConcContract {    
 id: ID
  aProperty: Int
  anotherProperty: String        
}

1 个答案:

答案 0 :(得分:1)

从SPQR的角度来看,这与POJO没有什么不同,因为SPQR只关心类型。

默认情况下,对于所有嵌套类(在您的情况下为MyCayenneClass),将显示看起来像getter的所有内容。对于顶级类(在您的情况下为MyRepository),默认情况下仅公开带注释的方法。并且必须至少公开一个顶级方法,否则您的架构无效。

错误,只是意味着没有发现单个顶级查询。我看到@GraphQLQuery注释被注释掉了。这是故意的吗?使用默认配置,这不会公开任何查询。

您可以注册其他ResolverBuilder,例如PublicResolverBuilder(或您自己的实现/扩展名),如果您想要公开未注释的方法。

E.g。

generator.withOperationsFromSingleton(new MyRepository(), new PublicResolverBuilder())

这将公开该类的所有公共方法。

这是我用v0.9.6尝试的一个稍微简化的例子,似乎按预期工作(我知道你在错误文本中使用了一个相当旧的版本)。

public class MyRepository {

    @GraphQLQuery //not commented out
    public MyCayenneClass find(Integer in) {
        return new MyCayenneClass();
    }
}

// extends CayenneDataObject because I don't know where to get the 
// writeProperty and readProperty from
// but shouldn't change anything from SPQR's perspective
public class MyCayenneClass extends CayenneDataObject {
    public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
    public static final Property<String> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);

    public void setAProperty(Integer aProperty) {
        writeProperty("aProperty", aProperty);
    }

    public Integer getAProperty() {
        return (Integer)readProperty("aProperty");
    }

    public void setAnotherProperty(String anotherProperty) {
        writeProperty("anotherProperty", anotherProperty);
    }

    public String getAnotherProperty() {
        return (String)readProperty("anotherProperty");
    }
}

您可以应用更多自定义项,具体取决于您最终需要的内容,但从目前的问题来看,您似乎不需要任何其他内容......

要覆盖用于嵌套类的ResolverBuilder,您有2个选项。

1)全局注册,所以所有嵌套类型都使用它:

generator.withNestedResolverBuilders(customBuilder)

2)或每种类型:

.withNestedResolverBuildersForType(MyCayenneClass.class, new BeanResolverBuilder())

但这很少需要......