我最近将我的应用引擎 SDK 从 1.7.7.1 升级到 1.8.5,并且我的端点 API 停止工作。我的 API 浏览器甚至无法加载。调高日志级别后,当我尝试访问 API 资源管理器时发现了以下错误。我的工作区和谷歌应用程序引擎遇到了一些问题,所以我决定使用最新的应用程序引擎 SDK(1.8 .5) 我通过市场安装的。我创建了一个名为 Book 的基本实体并生成了一个名为 BookEndpoint 的端点(代码见下文),但错误仍然存在。
有任何想法吗?
FINE: started Server@4c469ca0
Oct 08, 2013 5:29:20 PM com.google.apphosting.utils.jetty.JettyLogger debug
FINE: File added: C:\Users\Daniel\workspace\wspace_rebuild\testgce\war\WEB-INF\appengine-web.xml
Oct 08, 2013 5:29:20 PM com.google.appengine.tools.development.AbstractModule startup
INFO: Module instance default is running at http:// localhost:8888/
Oct 08, 2013 5:29:20 PM com.google.appengine.tools.development.AbstractModule startup
INFO: The admin console is running at http:// localhost:8888/_ah/admin
Oct 08, 2013 1:29:20 PM com.google.appengine.tools.development.DevAppServerImpl doStart
INFO: Dev App Server is now running
Oct 08, 2013 1:29:47 PM com.google.appengine.tools.development.DevAppServerModulesFilter getCurrentModuleInstance
FINE: Exception getting module instance
com.google.appengine.api.labs.modules.ModulesException: No valid instance id for this instance.
at com.google.appengine.api.labs.modules.ModulesServiceImpl.getCurrentInstanceId(ModulesServiceImpl.java:68)
at com.google.appengine.tools.development.DevAppServerModulesFilter.getCurrentModuleInstance(DevAppServerModulesFilter.java:210)
at com.google.appengine.tools.development.DevAppServerModulesFilter.isLoadBalancingRequest(DevAppServerModulesFilter.java:186)
at com.google.appengine.tools.development.DevAppServerModulesFilter.getRequestType(DevAppServerModulesFilter.java:175)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:113)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:97)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:485)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
package com.dan;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.google.appengine.api.datastore.Key;
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private String name;
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.dan;
import com.dan.EMF;
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 com.google.appengine.api.datastore.Cursor;
import com.google.appengine.datanucleus.query.JPACursorHelper;
import java.util.List;
import javax.annotation.Nullable;
import javax.inject.Named;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
@Api(name = "bookendpoint", namespace = @ApiNamespace(ownerDomain = "dan.com", ownerName = "dan.com", packagePath = ""))
public class BookEndpoint {
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* @return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
@SuppressWarnings({ "unchecked", "unused" })
@ApiMethod(name = "listBook")
public CollectionResponse<Book> listBook(
@Nullable @Named("cursor") String cursorString,
@Nullable @Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<Book> execute = null;
try {
mgr = getEntityManager();
Query query = mgr.createQuery("select from Book as Book");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<Book>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (Book obj : execute);
} finally {
mgr.close();
}
return CollectionResponse.<Book> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
/**
* This method gets the entity having primary key id. It uses HTTP GET method.
*
* @param id the primary key of the java bean.
* @return The entity with primary key id.
*/
@ApiMethod(name = "getBook")
public Book getBook(@Named("id") Long id) {
EntityManager mgr = getEntityManager();
Book book = null;
try {
book = mgr.find(Book.class, id);
} finally {
mgr.close();
}
return book;
}
/**
* This inserts a new entity into App Engine datastore. If the entity already
* exists in the datastore, an exception is thrown.
* It uses HTTP POST method.
*
* @param book the entity to be inserted.
* @return The inserted entity.
*/
@ApiMethod(name = "insertBook")
public Book insertBook(Book book) {
EntityManager mgr = getEntityManager();
try {
if (containsBook(book)) {
throw new EntityExistsException("Object already exists");
}
mgr.persist(book);
} finally {
mgr.close();
}
return book;
}
/**
* This method is used for updating an existing entity. If the entity does not
* exist in the datastore, an exception is thrown.
* It uses HTTP PUT method.
*
* @param book the entity to be updated.
* @return The updated entity.
*/
@ApiMethod(name = "updateBook")
public Book updateBook(Book book) {
EntityManager mgr = getEntityManager();
try {
if (!containsBook(book)) {
throw new EntityNotFoundException("Object does not exist");
}
mgr.persist(book);
} finally {
mgr.close();
}
return book;
}
/**
* This method removes the entity with primary key id.
* It uses HTTP DELETE method.
*
* @param id the primary key of the entity to be deleted.
*/
@ApiMethod(name = "removeBook")
public void removeBook(@Named("id") Long id) {
EntityManager mgr = getEntityManager();
try {
Book book = mgr.find(Book.class, id);
mgr.remove(book);
} finally {
mgr.close();
}
}
private boolean containsBook(Book book) {
EntityManager mgr = getEntityManager();
boolean contains = true;
try {
Book item = mgr.find(Book.class, book.getKey());
if (item == null) {
contains = false;
}
} finally {
mgr.close();
}
return contains;
}
private static EntityManager getEntityManager() {
return EMF.get().createEntityManager();
}
}
{
"extends" : "thirdParty.api",
"abstract" : false,
"root" : "https://appname.appspot.com/_ah/api",
"name" : "bookendpoint",
"version" : "v1",
"defaultVersion" : false,
"adapter" : {
"bns" : "https://appname.appspot.com/_ah/spi",
"deadline" : 10.0,
"type" : "lily"
},
"auth" : {
"allowCookieAuth" : false
},
"frontendLimits" : {
"unregisteredUserQps" : -1,
"unregisteredQps" : -1,
"unregisteredDaily" : -1,
"rules" : [ ]
},
"cacheControl" : {
"type" : "no-cache",
"maxAge" : 0
},
"ownerDomain" : "dan.com",
"ownerName" : "dan.com",
"methods" : {
"bookendpoint.removeBook" : {
"path" : "book/{id}",
"httpMethod" : "DELETE",
"authLevel" : "NONE",
"scopes" : [ "https://www.googleapis.com/auth/userinfo.email" ],
"audiences" : [ ],
"clientIds" : [ "292824132082.apps.googleusercontent.com" ],
"rosyMethod" : "com.dan.BookEndpoint.removeBook",
"request" : {
"parameters" : {
"id" : {
"type" : "int64",
"required" : true
}
},
"body" : "empty"
},
"response" : {
"body" : "empty"
}
},
"bookendpoint.insertBook" : {
"path" : "book",
"httpMethod" : "POST",
"authLevel" : "NONE",
"scopes" : [ "https://www.googleapis.com/auth/userinfo.email" ],
"audiences" : [ ],
"clientIds" : [ "292824132082.apps.googleusercontent.com" ],
"rosyMethod" : "com.dan.BookEndpoint.insertBook",
"request" : {
"body" : "autoTemplate(backendRequest)",
"bodyName" : "resource"
},
"response" : {
"body" : "autoTemplate(backendResponse)"
}
},
"bookendpoint.getBook" : {
"path" : "book/{id}",
"httpMethod" : "GET",
"authLevel" : "NONE",
"scopes" : [ "https://www.googleapis.com/auth/userinfo.email" ],
"audiences" : [ ],
"clientIds" : [ "292824132082.apps.googleusercontent.com" ],
"rosyMethod" : "com.dan.BookEndpoint.getBook",
"request" : {
"parameters" : {
"id" : {
"type" : "int64",
"required" : true
}
},
"body" : "empty"
},
"response" : {
"body" : "autoTemplate(backendResponse)"
}
},
"bookendpoint.updateBook" : {
"path" : "book",
"httpMethod" : "PUT",
"authLevel" : "NONE",
"scopes" : [ "https://www.googleapis.com/auth/userinfo.email" ],
"audiences" : [ ],
"clientIds" : [ "292824132082.apps.googleusercontent.com" ],
"rosyMethod" : "com.dan.BookEndpoint.updateBook",
"request" : {
"body" : "autoTemplate(backendRequest)",
"bodyName" : "resource"
},
"response" : {
"body" : "autoTemplate(backendResponse)"
}
},
"bookendpoint.listBook" : {
"path" : "book",
"httpMethod" : "GET",
"authLevel" : "NONE",
"scopes" : [ "https://www.googleapis.com/auth/userinfo.email" ],
"audiences" : [ ],
"clientIds" : [ "292824132082.apps.googleusercontent.com" ],
"rosyMethod" : "com.dan.BookEndpoint.listBook",
"request" : {
"parameters" : {
"cursor" : {
"type" : "string",
"required" : false
},
"limit" : {
"type" : "int32",
"required" : false
}
},
"body" : "empty"
},
"response" : {
"body" : "autoTemplate(backendResponse)"
}
}
},
"descriptor" : {
"schemas" : {
"Book" : {
"id" : "Book",
"type" : "object",
"properties" : {
"key" : {
"$ref" : "Key"
},
"name" : {
"type" : "string"
}
}
},
"Key" : {
"id" : "Key",
"type" : "object",
"properties" : {
"kind" : {
"type" : "string"
},
"appId" : {
"type" : "string"
},
"id" : {
"type" : "string",
"format" : "int64"
},
"name" : {
"type" : "string"
},
"parent" : {
"$ref" : "Key"
},
"complete" : {
"type" : "boolean"
},
"namespace" : {
"type" : "string"
}
}
},
"CollectionResponse_Book" : {
"id" : "CollectionResponse_Book",
"type" : "object",
"properties" : {
"items" : {
"type" : "array",
"items" : {
"$ref" : "Book"
}
},
"nextPageToken" : {
"type" : "string"
}
}
}
},
"methods" : {
"com.dan.BookEndpoint.removeBook" : {
},
"com.dan.BookEndpoint.insertBook" : {
"request" : {
"$ref" : "Book"
},
"response" : {
"$ref" : "Book"
}
},
"com.dan.BookEndpoint.getBook" : {
"response" : {
"$ref" : "Book"
}
},
"com.dan.BookEndpoint.updateBook" : {
"request" : {
"$ref" : "Book"
},
"response" : {
"$ref" : "Book"
}
},
"com.dan.BookEndpoint.listBook" : {
"response" : {
"$ref" : "CollectionResponse_Book"
}
}
}
}
}