I am just starting out on GAE and cloud endpoints. I have created a sample persistent class and I generated the enpoint class using the google menu in Eclipse. Now I was just following some tutorial on how to use curl
and get back nice json
string and apparently when I trying to list all values its throwing a nullpointerexception
, surprisingly when I provide an id with the url string then it magically works. Now, my concern is with this two method viz listContinent
and getContinent
This is what is creating the error
curl http://localhost:8888/_ah/api/app/v1/continent
which is calling the listContinent
method raising the error.
and this one just works
curl http://localhost:8888/_ah/api/app/v1/continent/1
which is calling the getContinent
method and when the correct Id
is passed via the url it works as expected.
This is my endpoint class -
@Api(name = "app")
public class ContinentEndpoint {
@SuppressWarnings({ "cast", "unchecked" })
public List<Continent> listContinent() {
PersistenceManager mgr = getPersistenceManager();
List<Continent> result = new ArrayList<Continent>();
try {
Query query = mgr.newQuery(Continent.class);
for (Object obj : (List<Object>) query.execute()) {
result.add(((Continent) obj));
}
} finally {
mgr.close();
}
return result;
}
public Continent getContinent(@Named("id") Long id) {
PersistenceManager mgr = getPersistenceManager();
Continent continent = null;
try {
continent = mgr.getObjectById(Continent.class, id);
} finally {
mgr.close();
}
return continent;
}
private static PersistenceManager getPersistenceManager() {
return PMF.get().getPersistenceManager();
}
}
and this is my persistent class -
@PersistenceCapable(identityType = IdentityType.APPLICATION)
@Version(strategy = VersionStrategy.VERSION_NUMBER)
public class Continent {
public long getContinentId() {
return continentId;
}
public void setContinentId(long continentId) {
this.continentId = continentId;
}
public String getContinentName() {
return continentName;
}
public void setContinentName(String continentName) {
this.continentName = continentName;
}
public Date getCreatedOn() {
return createdOn;
}
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private long continentId;
private String continentName;
private Date createdOn = new Date();
}
This is my stacktrace
Nov 12, 2012 3:07:10 PM com.google.apphosting.utils.jetty.JettyLogger info
INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
Nov 12, 2012 3:07:10 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
INFO: Successfully processed /home/soham/Workspace/cloudcv/war/WEB-INF/appengine-web.xml
Nov 12, 2012 3:07:10 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed /home/soham/Workspace/cloudcv/war/WEB-INF/web.xml
Nov 12, 2012 8:37:11 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The server is running at http://localhost:8888/
Nov 12, 2012 8:37:11 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The admin console is running at http://localhost:8888/_ah/admin
Nov 12, 2012 8:37:53 PM com.google.api.server.spi.SystemService invokeServiceMethod
SEVERE: null
java.lang.NullPointerException
at com.google.appengine.datanucleus.query.QueryEntityPKFetchFieldManager.fetchLongField(QueryEntityPKFetchFieldManager.java:74)
at org.datanucleus.identity.IdentityUtils.getApplicationIdentityForResultSetRow(IdentityUtils.java:101)
at com.google.appengine.datanucleus.EntityUtils.entityToPojo(EntityUtils.java:1009)
at com.google.appengine.datanucleus.query.DatastoreQuery$2.apply(DatastoreQuery.java:228)
at com.google.appengine.datanucleus.query.DatastoreQuery$2.apply(DatastoreQuery.java:225)
at com.google.appengine.datanucleus.query.LazyResult.resolveNext(LazyResult.java:96)
at com.google.appengine.datanucleus.query.LazyResult$LazyAbstractListIterator.computeNext(LazyResult.java:229)
at com.google.appengine.datanucleus.query.AbstractIterator.tryToComputeNext(AbstractIterator.java:131)
at com.google.appengine.datanucleus.query.AbstractIterator.hasNext(AbstractIterator.java:126)
at com.google.appengine.datanucleus.query.LazyResult$AbstractListIterator.hasNext(LazyResult.java:183)
at com.cloudcv.ContinentEndpoint.listContinent(ContinentEndpoint.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:254)
at com.google.api.server.spi.SystemServiceServlet.execute(SystemServiceServlet.java:135)
at com.google.api.server.spi.SystemServiceServlet.doPost(SystemServiceServlet.java:106)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
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:94)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:383)
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.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
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)
I did some debugging and I found out that the query in Query query = mgr.newQuery(Continent.class);
is not returning anything and the for each
loop is not populating the ArrayList
.
You can't use long
as the primary key type. I'd suggest using Long
instead. You can read about the acceptable key types here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With