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 в любом случае...
Ответы
Ответ 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
, и похоже, что это сработало так же хорошо, как и в моем случае, поскольку проблема здесь в основном связана с тем, что конечная точка не поддерживает параметризованные типы.