我正在尝试创建一个与Google App Engine交互以在google datastore中加载和保存实体的Android应用程序。 我认为我的配置是正确的,但我不知道是否可以上传我的应用程序进行测试。 它一直无响应,然后给我这个错误:
SEVERE: Endpoints configuration not updated. The app returned an error when the Google Cloud Endpoints server attempted to communicate with it.
然而,如果我更改版本号,则新版本即使收到此消息后也会出现在我的在线控制台中。我已经阅读了Google关于Datastore的所有文档,但无法找出问题所在。我遇到这个问题已经一个月了,一直没有找到解决办法。我在某个地方读到,如果应用程序包含错误,则不会上传,因此我将包含所有代码。我也不知道我在做什么,甚至不确定我是否在正确的轨道上工作,所以如果您注意到任何愚蠢的事情,请告诉我。非常感谢您提前的帮助,如果您能为我修复这个问题,您将是我的英雄和上帝。
这是我的端点:
package com.polo.backend.endpoints;
/**
* Created by sagesmith on 4/16/16.
*
* Is used to interact with the server
*/
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.ConflictException;
import com.google.api.server.spi.response.NotFoundException;
import com.googlecode.objectify.Ref;
import com.polo.backend.services.ObjcfyService;
import com.polo.backend.entities.Event;
import com.polo.backend.entities.User;
import java.util.List;
import javax.inject.Named;
/**
*
*/
@Api(
name = "userEndpoint",
version = "v1",
namespace = @ApiNamespace(
ownerDomain = "backend.polo.com",
ownerName = "backend.polo.com",
packagePath = ""
)
)
public class UserEndpoint {
/**
* Registers the two entities used in this class
*/
public UserEndpoint(){
ObjcfyService.register(User.class);
ObjcfyService.register(Event.class);
}
@ApiMethod(name = "insertUser")
/**
* Inserts a new {@code User} into the data store
*/
public void insertUser(User user) throws ConflictException, NotFoundException{
if(getUser(user.getUsername()) != null){
throw new ConflictException("Object already exists");
}
}
/**
*
* @param user
* @throws NotFoundException
*/
@ApiMethod(name = "updateUser")
public void updateUser(User user) throws NotFoundException{
if(getUser(user.getUsername()) != null) {
ObjcfyService.objectify().save().entity(user).now();
}
}
/**
*
* @param username
* @throws NotFoundException
*/
@ApiMethod(name = "removeUser")
public void removeUser(@Named("username") String username) throws NotFoundException{
User record = getUser(username);
if(record != null){
ObjcfyService.objectify().delete().entity(record).now();
}
}
/**
*
* @param username
* @return
* @throws NotFoundException
*/
@ApiMethod(name = "getUser")
public User getUser(@Named("username") String username) throws NotFoundException{
User user = ObjcfyService.objectify().load().type(User.class).id(username).now();
if(user != null) {
List<Ref<User>> friendRefs = user.getFriendRefs();
List<Ref<Event>> repeatingEventRefs = user.getRepeatingEventRefs();
List<Ref<Event>> nonRepeatingEventRefs = user.getNonRepeatingEventRefs();
for (Ref<User> friendRef : friendRefs) {
user.addFriend(friendRef.get());
}
for (Ref<Event> repeatingEventRef : repeatingEventRefs) {
user.addRepeatingEvent(repeatingEventRef.get());
}
for (Ref<Event> nonRepeatingEventRef : nonRepeatingEventRefs) {
user.addNonRepeatingEvent(nonRepeatingEventRef.get());
}
} else{
throw new NotFoundException("User not found");
}
return user;
}
}
这是我的用户实体:
package com.polo.backend.entities;
/**
* Created by sagesmith on 4/16/16.
*/
import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiResourceProperty;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.Load;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
@Entity
public class User {
@Id private String username = null;
@Index private String firstName = null;
@Index private String lastName = null;
@Nullable private String status = null;
@Nullable private String location = null;
@Load @Nullable private List<Ref<User>> friendRefs = new ArrayList<>();
@Load @Nullable private List<Ref<Event>> nonRepeatingEventRefs = new ArrayList<>();
@Load @Nullable private List<Ref<Event>> repeatingEventRefs = new ArrayList<>();
@Nullable public List<User> friends = new ArrayList<>();
@Nullable public List<Event> nonRepeatingEvents = new ArrayList<>();
@Nullable public List<Event> repeatingEvents = new ArrayList<>();
/**
*Returns the first name from the {@code User}
*
* @return the first name of the {@code User} as a {@code String}
*/
public String getFirstName(){
return firstName;
}
/**
* Returns the last name from the {@code User}
*
* @return the last name of the {@code User} as a {@code String}
*/
public String getLastName(){
return lastName;
}
/**
* Return the username from the user
*
* @return the username of the user as a String
*/
public String getUsername(){
return username;
}
/**
* Sets the username of the {@code User}
*
* @param username Username to set the {@code User}'s username to
*/
public void setUsername(String username){
this.username = username;
}
/**
* Sets the firstName of the {@code User}
*
* @param firstName First name to set the {@code User}'s first name to
*/
public void setFirstName(String firstName){
this.firstName = firstName;
}
/**
* Sets the lastName of the {@code User}
*
* @param lastName Last name to set the {@code User}'s last name to
*/
public void setLastName(String lastName){
this.lastName = lastName;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Adds a friend to the {@code User}'s list of friends
*
* @param user User to add
*/
public void addFriendRef(User user){
friendRefs.add(Ref.create(user));
}
/**
* Returns the {@code User}'s friends
*
* @return {@code List<Users>} the friends of the {@code User}
*/
public List<User> getFriends(){
return friends;
}
/**
* Adds a friend to the users {@code List} of friends
*
* @param user {@code User} to add as a friend
*/
public void addFriend(User user){
friends.add(user);
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Returns a {@code List<Ref<User>>} of references to the {@code User}'s friends
*
* @return {@code List<Ref<User>>}
*/
public List<Ref<User>> getFriendRefs(){
return friendRefs;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Returns a {@code List<Ref<Event>>} of references to the {@code User}'s repeating
* {@code Event}s
*
* @return {@code List<Ref<Event>>}
*/
public List<Ref<Event>> getRepeatingEventRefs(){
return repeatingEventRefs;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Returns a {@code List<Ref<Event>>} of references to the {@code User}'s non repeating
* {@code Event}s
*
* @return {@code List<Ref<Event>>}
*/
public List<Ref<Event>> getNonRepeatingEventRefs(){
return nonRepeatingEventRefs;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Sets the {@code User}'s status to a given {@code String}
*
* @param status {@code String} to set an {@code Users}'s status to
*/
public void setStatus(String status){
this.status = status;
}
/**
* Returns the {@code User}'s status as a {@code String}
*
* @return {@code String} status
*/
public String getStatus(){
return status;
}
/**
* Returns the {@code User}'s location as a {@code String}
*
* @return {@code String} location
*/
public String getLocation(){
return location;
}
/**
* Sets the {@code User}'s location to a given {@code String}
*
* @param location {@code String} to set an {@code Users}'s location to
*/
public void setLocation(String location){
this.location = location;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Adds a repeating {@code Event} to the {@code User}'s schedule
*
* @param event {@code Event} to add to the {@code User}'s schedule
*/
public void addRepeatingEvent(Event event){
repeatingEventRefs.add(Ref.create(event));
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
/**
* Adds a non repeating {@code Event} to the user's schedule
*
* @param event Event to add to the the user's schedule
*/
public void addNonRepeatingEvent(Event event){
nonRepeatingEventRefs.add(Ref.create(event));
}
/**
* Returns a {@code List<Event>} of repeating {@code Event}s from the user's schedule
*
* @return List<Event> repeatingEvents from user's schedule
*/
public List<Event> getRepeatingEvents(){
return repeatingEvents;
}
/**
* Returns a list of nonRepeatingEvents from the user's schedule
*
* @return List<Event> repeatingEvents from user's schedule
*/
public List<Event> getNonRepeatingEvents(){
return nonRepeatingEvents;
}
}
以及我的事件实体:
package com.polo.backend.entities;
import com.googlecode.objectify.annotation.Entity;
/**
* Created by sagesmith on 5/3/16.
*/
@Entity
public class Event {
private Integer startIndex;
private Integer endIndex;
private Byte[] color;
public Event(Integer startIndex, Integer endIndex, Byte red, Byte green, Byte blue){
this.startIndex = startIndex;
this.endIndex = endIndex;
color = new Byte[]{red, green, blue};
}
}
我的ObjectifyService:
package com.polo.backend.services;
/**
* Created by sagesmith on 4/16/16.
*/
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyService;
public class ObjcfyService {
public static void register(Class<?> eClass){
ObjectifyService.register(eClass);
}
public static Objectify objectify(){
return ObjectifyService.ofy();
}
public static ObjectifyFactory objectifyFactory(){
return ObjectifyService.factory();
}
}
这是我的appengine-web.xml文件,我已经用my_id替换了我的appid,出于明显的原因:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>my_id</application>
<version>1</version>
<threadsafe>true</threadsafe>
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
这是我的web.xml文件。
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value>com.polo.backend.endpoints.UserEndpoint</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
这是我在Android应用程序中使用的与数据存储通信的AsyncTask,我再次用my_id替换了我的应用程序ID:
package com.polo.client;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.polo.StaticAssets;
import com.polo.activity.Home;
import com.polo.backend.userEndpoint.UserEndpoint;
import com.polo.backend.userEndpoint.model.User;
import java.io.IOException;
/**
* Created by sagesmith on 4/17/16.
*/
public class UserAsyncTask extends AsyncTask<Void, Void, User>{
private static UserEndpoint userApiService = null;
private Home context;
private String username;
/**
*
* @param context
*/
public UserAsyncTask(Home context){
this.context = context;
username = StaticAssets.getUserName(context);
}
/**
*
* @param params
* @return
*/
@Override
protected User doInBackground(Void... params){
if(userApiService == null){
UserEndpoint.Builder builder = new UserEndpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(),
null
)
.setRootUrl("https://my_id.appspot.com/_ah/api/");
userApiService = builder.build();
}
User user = null;
try{
user = userApiService.getUser(username).execute();
} catch (IOException e){
Log.e("User not found", e.getMessage());
}
return user;
}
/**
*
* @param result
*/
@Override
protected void onPostExecute(User result) {
if(result!=null)
Toast.makeText(context, result.getFirstName(), Toast.LENGTH_LONG).show();
}
}