当我为我的终端生成客户端库时,我发现了一种奇怪的行为。
在我的appengine项目中,我有两个端点类来处理两个实体的操作:
实体组的GroupEndpoint
实体联系的ContactEndpoint
组实体有一个联系人列表,因为有时当调用GroupEndpoint的API方法时,我必须更新其联系人。
问题是当我生成客户端库时,Contact实体是在两个不同的命名空间中生成的(每个端点一个),这非常令人困惑,因为我最终得到了相同的类(完全相同)两次。 / p>
以下是一个例子:
Group.java
package backend;
import java.util.List;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable
public class Group {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
private List<Contact> contactList;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Contact> getContactList() {
return contactList;
}
public void setContactList(List<Contact> contactList) {
this.contactList = contactList;
}
}
GroupEndpoint.java(示例的虚拟代码)
package backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.response.CollectionResponse;
import javax.annotation.Nullable;
import javax.inject.Named;
@Api(name = "groupendpoint")
public class GroupEndpoint {
@ApiMethod(name = "listContact")
public CollectionResponse<Group> listGroup(
@Nullable @Named("cursor") String cursorString,
@Nullable @Named("limit") Integer limit) {
return null;
}
}
Contact.java
package backend;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable
public class Contact {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
}
ContactEndpoint.java(示例的虚拟代码)
package backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.CollectionResponse;
import javax.annotation.Nullable;
import javax.inject.Named;
@Api(name = "contactendpoint")
public class ContactEndpoint {
@ApiMethod(name = "listContact")
public CollectionResponse<Contact> listContact(
@Nullable @Named("cursor") String cursorString,
@Nullable @Named("limit") Integer limit) {
return null;
}
}
的build.gradle
// Currently, the appengine gradle plugin's appengine devappserver launch doesn't interact well with Intellij/AndroidStudio's
// Gradle integration. As a temporary solution, please launch from the command line.
// ./gradlew modulename:appengineRun
// If you would like more information on the gradle-appengine-plugin please refer to the github page
// https://github.com/GoogleCloudPlatform/gradle-appengine-plugin
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.appengine:gradle-appengine-plugin:1.9.1'
}
}
repositories {
mavenCentral();
}
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'
sourceCompatibility = 1.7
targetCompatibility = 1.7
dependencies {
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.1'
compile 'javax.servlet:servlet-api:2.5'
compile 'com.google.appengine:appengine-endpoints:1.9.1'
compile 'com.google.appengine:appengine-endpoints-deps:1.9.1'
compile 'javax.servlet:servlet-api:2.5'
compile 'org.datanucleus:datanucleus-core:3.2.13'
compile 'org.datanucleus:datanucleus-api-jpa:3.2.3'
compile 'javax.jdo:jdo-api:3.0.1'
compile 'org.datanucleus:datanucleus-api-jdo:3.2.8'
compile 'org.datanucleus:datanucleus-jdo-query:3.0.2'
compile 'com.google.appengine.orm:datanucleus-appengine:2.1.2'
compile 'org.apache.geronimo.specs:geronimo-jpa_2.0_spec:1.1'
compile 'com.ganyo:gcm-server:1.0.2'
compile 'net.sf.javaprinciples.persistence:persistence-api:4.0.0'
}
appengine {
downloadSdk = true
appcfg {
oauth2 = true
}
}
当我生成客户端库时,它会在我的构建目录中创建groupendpoint-v1-java.zip和contactendpoint-v1-java.zip。如果我提取这些文件,我会看到每个zip文件都有一个Contact类。
对于groupendpoint-v1-java.zip:
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
/*
* This code was generated by https://code.google.com/p/google-apis-client-generator/
* (build: 2014-04-15 19:10:39 UTC)
* on 2014-04-22 at 12:22:19 UTC
* Modify at your own risk.
*/
package com.appspot.myapplicationid.groupendpoint.model;
/**
* Model definition for Contact.
*
* <p> This is the Java data model class that specifies how to parse/serialize into the JSON that is
* transmitted over HTTP when working with the groupendpoint. For a detailed explanation see:
* <a href="http://code.google.com/p/google-http-java-client/wiki/JSON">http://code.google.com/p/google-http-java-client/wiki/JSON</a>
* </p>
*
* @author Google, Inc.
*/
@SuppressWarnings("javadoc")
public final class Contact extends com.google.api.client.json.GenericJson {
@Override
public Contact set(String fieldName, Object value) {
return (Contact) super.set(fieldName, value);
}
@Override
public Contact clone() {
return (Contact) super.clone();
}
}
对于contactendpoint-v1-java.zip:
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
/*
* This code was generated by https://code.google.com/p/google-apis-client-generator/
* (build: 2014-04-15 19:10:39 UTC)
* on 2014-04-22 at 12:22:21 UTC
* Modify at your own risk.
*/
package com.appspot.myapplicationid.contactendpoint.model;
/**
* Model definition for Contact.
*
* <p> This is the Java data model class that specifies how to parse/serialize into the JSON that is
* transmitted over HTTP when working with the contactendpoint. For a detailed explanation see:
* <a href="http://code.google.com/p/google-http-java-client/wiki/JSON">http://code.google.com/p/google-http-java-client/wiki/JSON</a>
* </p>
*
* @author Google, Inc.
*/
@SuppressWarnings("javadoc")
public final class Contact extends com.google.api.client.json.GenericJson {
@Override
public Contact set(String fieldName, Object value) {
return (Contact) super.set(fieldName, value);
}
@Override
public Contact clone() {
return (Contact) super.clone();
}
}
请注意,唯一的区别是它们属于不同的命名空间。当我使用客户端库时,这非常令人困惑。
我该如何避免这种行为?
感谢。
答案 0 :(得分:0)
我遇到了同样的问题,我找到了解决这个问题的方法。它可能有一些优点和限制,但我会在这里介绍它们。
您拥有不同的模型(在客户端),因为它们位于不同的库中。例如,您的联系人列表将位于libcontactendpoint和另一个libgroupendpoint中,因为您的Contact类都在其中使用。
为了在客户端只有一个代表您的实体的类,您需要将它保留在一个端点(在Client项目中)。因此,一种方法是使用@Api注释。此注释用于所有端点类。因此,如果您的班级 GroupEndpoint 具有 @Api(name =“groupendpoint”),则会创建一个libgroupendpoint。如果要在同一端点中同时使用Contact和Group,而不需要重复,则端点类必须指向相同的API。 解决方案:
package backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.response.CollectionResponse;
import javax.annotation.Nullable;
import javax.inject.Named;
//Changing api name
@Api(name = "generalendpoint")
public class GroupEndpoint {
@ApiMethod(name = "listContact")
public CollectionResponse<Group> listGroup(
@Nullable @Named("cursor") String cursorString,
@Nullable @Named("limit") Integer limit) {
return null;
}
}
ContactEndpoint还有 generalendpoint (您可以使用任何名称相同的名称)。
package backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.CollectionResponse;
import javax.annotation.Nullable;
import javax.inject.Named;
@Api(name = "generalendpoint")
public class ContactEndpoint {
@ApiMethod(name = "listContact")
public CollectionResponse<Contact> listContact(
@Nullable @Named("cursor") String cursorString,
@Nullable @Named("limit") Integer limit) {
return null;
}
}
现在,你不会有这个问题。但是,请记住现在,在客户端,而不是使用Groupendpoint或Contactendpoint来执行操作并调用这些端点方法,现在必须使用Generalenpoint。
缺点:
1不是那么重要,因为你不编辑你的库,只需调用方法。在您的应用引擎项目中的类中创建方法时,需要注意第二个。