【发布时间】:2014-04-14 14:15:49
【问题描述】:
当我为我的端点生成客户端库时,我发现了一个奇怪的行为。
在我的 appengine 项目中,我有两个端点类来处理两个实体的操作:
实体组的GroupEndpoint
实体联系人的ContactEndpoint
组实体有一个联系人列表,因为有时当调用 GroupEndpoint 的 API 方法时,我必须更新它的联系人。
问题是当我生成客户端库时,Contact 实体是在两个不同的命名空间(每个端点一个)中生成的,这很令人困惑,因为我最终得到了同一个类(完全相同)两次。
这是一个例子:
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();
}
}
请注意,唯一的区别是它们属于不同的命名空间。当我使用客户端库时,这太令人困惑了。
如何避免这种行为?
谢谢。
【问题讨论】:
-
您是如何(使用哪些工具)生成客户端库的?
-
我在 Eclipse 中使用 Google 插件生成了客户端库,然后我迁移到了 Android Studio,使用 Gradle 的 appengine 插件得到了相同的结果。请参阅Google Plugin for Eclipse tutorial的步骤 3@
-
我现在看到了您的问题。现在我怀疑是否有办法避免这个问题。端点生成器正在创建类并确定命名空间......我在使用 .Net Web 服务时遇到了同样的问题,唯一的方法是在您的客户端代码中处理它。
标签: java google-app-engine google-cloud-endpoints