使用Cloud Endpoints在一次调用中保存引用的对象(通过Ref)

时间:2014-09-27 23:37:19

标签: java google-app-engine google-cloud-endpoints objectify

我使用objectify和Google Cloud Endpoints来开发应用程序的后端。我有一辆"卡车"具有参考(使用Ref)到"类别"类。它看起来像这样:

@Entity
@Cache
public class Truck {

   public @Id Long id;
   public String city;
   //...
   @Load Ref<PlaceCategory> category;

   public PlaceCategory getCategory(){
       return category.get();
   }

   public void setCategory(PlaceCategory category){
       this.category = Ref.create(category);
   }
}

当然,Category类只是另一个拥有它自己id的实体。

现在,构建API我希望能够 - 在一次调用中 - 插入一个包含Category对象的Truck对象。在这种情况下,请求正文将如下所示:

{
 "category": {
  "name": "Some category"
 },
 "city": "Some city"
}

(它只是来自API资源管理器的副本)。 但是,执行此请求时收到错误:

  

com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException:   没有课程&#39; entities.Category&#39;已注册(通过参考链:entities.Truck [\&#34; category \&#34;])

我当然在OfyService中注册了Category对象:

public class OfyService {

    static {
        factory().register(PlaceCategory.class);
    }

    public static Objectify ofy() {
        return ObjectifyService.ofy();
    }

    public static ObjectifyFactory factory() {
        return ObjectifyService.factory();
    }
}

我已经两次阅读了文档,但我仍然不知道问题出在哪里。没有明确表示我不能嵌入像这样的对象。经过2天的搜索和尝试我放弃了:)希望有人能帮助我理解。

2 个答案:

答案 0 :(得分:1)

以下代码非常接近您,在开发服务器和App Engine上都适合我。

我使用的是App Engine 1.8.9和Objectify 4.0b3,您是否正在使用旧版本而只需升级?

的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>hatanian.david.cloudplatform</groupId>
    <artifactId>endpoints-objectify-ref</artifactId>
    <packaging>war</packaging>
    <version>1.0</version>
    <name>Simple Endpoints API</name>

    <properties>
        <appengine.target.version>1.8.9</appengine.target.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <repositories>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.5</version>
        </dependency>
        <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-api-1.0-sdk</artifactId>
            <version>${appengine.target.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-endpoints</artifactId>
            <version>${appengine.target.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--<dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-testing</artifactId>
            <version>${appengine.target.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-api-stubs</artifactId>
            <version>${appengine.target.version}</version>
            <scope>test</scope>
        </dependency>-->
        <dependency>
            <groupId>com.googlecode.objectify</groupId>
            <artifactId>objectify</artifactId>
            <version>4.0b3</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <webXml>${project.build.directory}/generated-sources/appengine-endpoints/WEB-INF/web.xml</webXml>
                    <webResources>
                        <resource>
                            <!-- this is relative to the pom.xml directory -->
                            <directory>${project.build.directory}/generated-sources/appengine-endpoints</directory>
                            <!-- the list has a default value of ** -->
                            <includes>
                                <include>WEB-INF/*.discovery</include>
                                <include>WEB-INF/*.api</include>
                            </includes>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.google.appengine</groupId>
                <artifactId>appengine-maven-plugin</artifactId>
                <version>${appengine.target.version}</version>
                <configuration>
                    <enableJarClasses>false</enableJarClasses>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>endpoints_get_discovery_doc</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Ofyservice:

package hatanian.david.simpleendpoint;

import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyService;

public class OfyService {

    static {
        factory().register(PlaceCategory.class);
        factory().register(Truck.class);
    }

    public static Objectify ofy() {
        return ObjectifyService.ofy();
    }

    public static ObjectifyFactory factory() {
        return ObjectifyService.factory();
    }
}

PlaceCategory:

@Entity
public class PlaceCategory {
    @Id
    private String category;

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}

卡车:

@Entity
@Cache
public class Truck {

   public @Id Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Load
   Ref<PlaceCategory> category;

   public PlaceCategory getCategory(){
       return category.get();
   }

   public void setCategory(PlaceCategory category){
       this.category = Ref.create(category);
   }
}

终点:

@Api(name = "simple", version = "v1", scopes = {EndPointsConstants.EMAIL_SCOPE}, clientIds = {EndPointsConstants.WEB_CLIENT_ID, com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID})
public class SimpleEndpoint {
    private Logger log = Logger.getLogger(SimpleEndpoint.class.getName());

    @ApiMethod(name = "create", httpMethod = "post")
    public void create() {
        PlaceCategory placeCategory = new PlaceCategory();
        placeCategory.setCategory("testcategory");
        OfyService.ofy().save().entity(placeCategory).now();

        Truck truck = new Truck();
        truck.setCategory(placeCategory);
        truck.setId(1L);
        OfyService.ofy().save().entity(truck).now();
    }

    @ApiMethod(name = "gettruck", httpMethod = "get")
    public Truck getTruck() {
        return ObjectifyService.ofy().load().key(Key.create(Truck.class, 1L)).now();
    }
}

答案 1 :(得分:1)

您似乎错过了注册卡车级别。这样:

static 
{
   factory().register(PlaceCategory.class);
}

应该是(如Davids loooong例子中所示):

static 
{
   factory().register(PlaceCategory.class);
   factory().register(Truck.class);
}