I am building an Android App with the backend hosted on GAE. Right now I am trying to persist a POJO entity through Objectify to the Datastore. Following are the POJOs I am trying to persist.
@Entity
public class GenericLearnerProfile {
private String mName;
@Id
private String mEmailID;
private String mPhoneNo;
private String mImagePath;
private String mCurrentStatus;
private String mPassword;
//Default constructor required for persistence(serialization)
public GenericLearnerProfile(){}
//.......Other Getters, Setters and constructors follow
}
@Entity
public class TutorProfile extends GenericLearnerProfile {
private EducationalQualification[] educationalQualifications;
private Occupation occupation;
//Default constructor required for persistence(serialization)
public TutorProfile(){}
//.......Other Getters, Setters and constructors follow
}
As you can see, its a pretty simple hierarchy.
Problem: When I try to persist just GenericLearnerProfile
, it successfully happens but with TutorProfile, it throws out the following exception:
com.googlecode.objectify.SaveException: Error saving com.learncity.backend.persistence.TutorProfile@22fc69b4: id cannot be zero
at com.googlecode.objectify.impl.EntityMetadata.save(EntityMetadata.java:95)
at com.googlecode.objectify.impl.WriteEngine.save(WriteEngine.java:73)
at com.googlecode.objectify.impl.SaverImpl.entities(SaverImpl.java:60)
at com.googlecode.objectify.impl.SaverImpl.entity(SaverImpl.java:35)
at com.learncity.backend.persistence.TutorProfileEndpoint.insert(TutorProfileEndpoint.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:130)
at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:363)
at com.google.api.server.spi.SystemServiceServlet.execute(SystemServiceServlet.java:113)
at com.google.api.server.spi.SystemServiceServlet.doPost(SystemServiceServlet.java:71)
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.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:48)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
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:128)
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:63)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:50)
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.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
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:98)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:513)
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)
Caused by: java.lang.IllegalArgumentException: id cannot be zero
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:52)
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:47)
at com.googlecode.objectify.util.DatastoreUtils.createKey(DatastoreUtils.java:77)
at com.googlecode.objectify.impl.KeyMetadata.getRawKey(KeyMetadata.java:187)
at com.googlecode.objectify.impl.translate.EntityCreator.save(EntityCreator.java:54)
at com.googlecode.objectify.impl.translate.EntityCreator.save(EntityCreator.java:16)
at com.googlecode.objectify.impl.translate.ClassTranslator.saveSafe(ClassTranslator.java:136)
at com.googlecode.objectify.impl.translate.ClassTranslator.saveSafe(ClassTranslator.java:21)
at com.googlecode.objectify.impl.translate.NullSafeTranslator.save(NullSafeTranslator.java:25)
at com.googlecode.objectify.impl.translate.ArrayTranslatorFactory$1.save(ArrayTranslatorFactory.java:83)
at com.googlecode.objectify.impl.translate.ArrayTranslatorFactory$1.save(ArrayTranslatorFactory.java:39)
at com.googlecode.objectify.impl.PropertyPopulator.save(PropertyPopulator.java:135)
at com.googlecode.objectify.impl.translate.ClassPopulator.save(ClassPopulator.java:153)
at com.googlecode.objectify.impl.translate.ClassTranslator.saveSafe(ClassTranslator.java:138)
at com.googlecode.objectify.impl.translate.ClassTranslator.saveSafe(ClassTranslator.java:21)
at com.googlecode.objectify.impl.translate.NullSafeTranslator.save(NullSafeTranslator.java:25)
at com.googlecode.objectify.impl.EntityMetadata.save(EntityMetadata.java:89)
... 51 more
Note:
- All the embedded objects have long as an Id.
- It doesn't help if I make them Long. It then displays the error - "id cannot be null"
- I don't want to manually set the long ids for the embedded objects because it really doesn't make sense for the classes to necessarily have an id(other than for persistence)
Can anyone help me understand this exception and way around it?
The problem is with the expectation that Ids are autogenerated- They do but NOT for embedded entities. Source: https://groups.google.com/forum/#!topic/objectify-appengine/TC2G5I-GJ8w
So as @stickfigure mentioned here:
And,
Also, Riley says,
I solved my problem by making the Embedded objects as Non-entities and therefore no requirement of an ID for them - I removed the @Entity annotation from them and now it is working smoothly.