Генератор схем для классов ApacheCayenne

Я пытаюсь использовать SPQR для создания схемы GraphQL из класса, созданного Cayenne. Класс 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);
 }
}

* К вашему сведению. Если я объявлю схему. Код будет работать нормально

schema {
  query: Query
}

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

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

Сначала попробуйте установить последнюю версию SPQR (на данный момент 0.9.6). Кажется, что этот класс должен работать нормально. Я попробую позже и дам вам больше информации. Кстати, это не класс верхнего уровня, который вы регистрируете в SPQR, верно?

kaqqao 26.03.2018 09:20

Я не знаю, что делать с этим классом ... Откуда берутся writeProperty и readProperty? Не могли бы вы привести более полный пример, поскольку я совершенно не знаком с Cayenne? Важно увидеть, используется ли этот класс в качестве ввода или вывода, а также как настроен генератор схемы.

kaqqao 26.03.2018 11:38

Это классы Cayenne. то есть cayenne-server-4.0.B2.jar. Я обновил код

Graciano 26.03.2018 15:15

GraphQL прокомментировал, что я виноват при вставке кода сюда. Мое первое предположение о проблеме заключается в том, что SPQR не смог найти геттеры / сеттеры для свойств в классе. т.е. свойство <Integer> A_PROPERTY // получить / установить public void setAProperty (Integer aProperty) {writeProperty ("aProperty", aProperty); } общедоступное целое число getAProperty () {return (Целое число) readProperty ("aProperty"); }

Graciano 26.03.2018 15:42

Хм, похоже, репликация невозможна ... Ошибка утверждает, что ничего не было отображено на верхнем уровне. Может быть, поставить точку останова в AnnotatedResolverBuilder#buildQueryResolvers и проверить, возвращает ли он что-нибудь. Если у вас по-прежнему возникают проблемы, свяжитесь со мной по Gitter, и мы сможем разобраться в этом подробнее.

kaqqao 26.03.2018 16:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
163
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

С точки зрения SPQR, это не сильно отличается от POJO, поскольку SPQR заботится только о типах.

По умолчанию для всех вложенных классов (MyCayenneClass в вашем случае) будет показано все, что выглядит как геттер. Для классов верхнего уровня (MyRepository в вашем случае) по умолчанию доступны только аннотированные методы. И хотя бы один метод верхнего уровня должен быть открыт, иначе у вас будет недопустимая схема.

Ошибка в ее нынешнем виде означает, что не было обнаружено ни одного запроса верхнего уровня. Я вижу, что аннотация @GraphQLQuery закомментирована. Это намеренно? С конфигурацией по умолчанию это не приведет к появлению каких-либо запросов.

Вы можете зарегистрировать другой ResolverBuilder, например PublicResolverBuilder (или ваша собственная реализация / расширение), если вы хотите предоставить неаннотированные методы.

Например.

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

Но это очень редко нужно ...

Используя 0.9.1, при построении схемы Вызвано: java.lang.IndexOutOfBoundsException: Индекс: 0, Размер: 0 в java.base / java.util.LinkedList.checkElementIndex (LinkedList.‌ java: 559) в java.base /java.util.LinkedList.get(LinkedList.java:480) в io.leangen.graphql.util.ClassUtils.getCommonSuperType (ClassU‌ tils.java:396) в io.leangen.graphql.metadata.strategy.queryBDefaultO Uilder.resolveJavaTy‌ pe (DefaultOperationB‌ uilder.java:58) в io.leangen.graphql.metadata.strategy.query.DefaultOperationB‌ uilder.buildQuery (De‌ faultOperationBuilde‌ r.java:33) в io.leangen.graphql .generator.Opera

Graciano 26.03.2018 16:47

Попробую с 0.9.6

Graciano 26.03.2018 16:48

Нашел проблему (это на моей стороне). 0.9.6 дает лучшее сообщение об ошибке. Вызвано: io.leangen.graphql.generator.exceptions.TypeMappingException‌: для операции «XYZ» обнаружено несколько методов с разными типами возвращаемых значений. Найденные типы: [boolean, java.lang.String]. Если это сделано намеренно и вы хотите, чтобы GraphQL SPQR автоматически определял наиболее распространенный супертип, см. github.com/leangen/graphql-spqr/wiki/… в io.leangen.graphql.metadata.strategy.query.DefaultOperationB‌ uilder.resolveJavaTy‌ pe (DefaultOperationB‌ uilder.java:122)

Graciano 26.03.2018 17:38

@Graciano А, понятно. В каждом выпуске есть множество улучшений и исправлений ошибок, поэтому следите за обновлениями.

kaqqao 26.03.2018 17:40

Другие вопросы по теме