سؤال

I am using appengine cloud endpoints and objectify. I have previously deployed these endpoints before and now I am updating them and it is not working with Objectify. I have moved to a new machine and running latest appengine 1.8.6. Have tried putting objectify in the classpath and that did not work. I know this can work, what am I missing??

When running endpoints.sh:

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

UPDATE: I went back to my old computer and ran endpoints.sh on same endpoint and it worked fine. Old machine has 1.8.3. I am using objectify 3.1.

UPDATE 2: Updated my old machine to 1.8.6 and get same error as other machine. Leaves 2 possibilities: 1) Endpoints no longer support objectify 3.1 or 2) Endpoints have a bug in most recent version

Most likely #1...I've been meaning to update to 4.0 anyways...

هل كانت مفيدة؟

المحلول

Because of the popularity of Objectify, a workaround was added in prior releases to support the Key type, until a more general solution was available. Because the new solution is available, the workaround has been removed. There are two ways you can now approach the issue with the property.

  1. Add an @ApiResourceProperty annotation that causes the key to be omitted from your object during serialization. Use this approach if you want a simple solution and don't need access to the key in your clients.
  2. Add an @ApiTransformer annotation that provides a compatible mechanism to serialize/deserialize the field. Use this approach if need access to the key (or a representation of it) in your clients. As this requires writing a transformer class, it is more work than the first option.

نصائح أخرى

I came up with the following solution for my project:

@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;
}

I know, it's a little bit boilerplate, but hey - it works and adds some handy shortcut methods.

At first, I did not understand the answer given by Flori, and how useful it really is. Because others may benefit, I will give a short explanation.

As explained earlier, you can use @ApiTransformer to define a transformer for your class. This would transform an unserializable field, like those of type Key<myClass> into something else, like a Long.

It turns out that when a class is processed by GCE, methods called get{fieldName} and set{FieldName} are automatically used to transform the field {fieldName}. I have not been able to find this anywhere in Google's documentation.

Here is how I use it for the Key{Machine} property in my Exercise class:

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

  // ...
}

Others already mentioned how to approach this with @ApiResourceProperty and @ApiTransformer. But I do need the key available in client-side, and I don't wanna transform the whole entity for every one. I tried replacing the Objectify Key with com.google.appengine.api.datastore.Key, and it looks like it worked just fine as well in my case, since the problem here is mainly due to that endpoint does not support parameterized types.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top