Objectify с облачными конечными точками - программирование
Подтвердить что ты не робот

Objectify с облачными конечными точками

Я использую appengine cloud endpoints и объективирую. Ранее я использовал эти конечные точки, и теперь я их обновляю и не работает с Objectify. Я перешел на новую машину и выполнил последнюю версию приложения 1.8.6. Попробовали поставить объектизацию в classpath, и это не сработало. Я знаю, что это может работать, чего мне не хватает?

При запуске endpoints.sh:

Error: Parameterized type
   com.googlecode.objectify.Key<MyClass> not supported.

UPDATE: Я вернулся на свой старый компьютер и запустил endpoints.sh на той же конечной точке, и он работал нормально. Старая машина имеет 1.8.3. Я использую objectify 3.1.

ОБНОВЛЕНИЕ 2: Обновил мою старую машину до версии 1.8.6 и получил ту же ошибку, что и другая машина. Листья 2 возможности: 1) Конечные точки больше не поддерживают объективизацию 3.1  или 2) Конечные точки имеют ошибку в последней версии

Скорее всего, # 1... Я имел в виду обновление до 4.0 в любом случае...

4b9b3361

Ответ 1

Из-за популярности Objectify в предыдущих выпусках было добавлено обходное решение для поддержки типа Key, пока не было доступно более общее решение. Поскольку новое решение доступно, обходной путь был удален. Теперь вы можете подойти к проблеме с помощью двух способов.

  • Добавьте аннотацию @ApiResourceProperty, которая заставляет исключить ключ из вашего объекта во время сериализации. Используйте этот подход, если вы хотите простое решение и не нуждаетесь в доступе к ключу своих клиентов.
  • Добавьте аннотацию @ApiTransformer, которая обеспечивает совместимый механизм сериализации/десериализации поля. Используйте этот подход, если вам нужен доступ к ключу (или его представлению) в ваших клиентах. Поскольку для этого требуется написать класс трансформатора, это больше, чем первый вариант работы.

Ответ 2

Я придумал следующее решение для моего проекта:

@Entity
public class Car {

    @Id Long id;

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
    Key<Driver> driver;

    public Key<Driver> getDriver() {
        return driver;
    }

    public void setDriver(Key<Driver> driver) {
        this.driver = driver;
    }

    public Long getDriverId() {
        return driver == null ? null : driver.getId();
    }

    public void setDriverId(Long driverId) {
        driver = Key.create(Driver.class, driverId);
    }
}

@Entity
public class Driver {
    @Id Long id;
}

Я знаю, это немного шаблонный, но hey - он работает и добавляет некоторые удобные методы быстрого доступа.

Ответ 3

Сначала я не понял ответ, данный Флори, и насколько он полезен. Потому что другие могут выиграть, я дам короткое объяснение.

Как объяснялось ранее, вы можете использовать @ApiTransformer для определения трансформатора для вашего класса. Это превратило бы неэриализуемое поле, подобное типу Key<myClass>, в нечто другое, например Long.

Оказывается, когда класс обрабатывается GCE, методы, называемые get{fieldName} и set{FieldName}, автоматически используются для преобразования поля {fieldName}. Я не смог найти его в документации Google.

Вот как я использую его для свойства Key{Machine} в классе Exercise:

public class Exercise {
  @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
  public Key<Machine> machine;
  // ... more properties

  public Long getMachineId() {
    return this.machine.getId();
  }

  public void setMachineId(Long machineId) {
    this.machine = new Key<Machine>(Machine.class, machineId);
  }

  // ...
}

Ответ 4

Другие уже упомянули, как подойти к этому с помощью @ApiResourceProperty и @ApiTransformer. Но мне нужен ключ, доступный на стороне клиента, и я не хочу преобразовывать весь объект для каждого. Я попытался заменить ключ Objectify ключом com.google.appengine.api.datastore.Key, и похоже, что это сработало так же хорошо, как и в моем случае, поскольку проблема здесь в основном связана с тем, что конечная точка не поддерживает параметризованные типы.