Reputation: 53
I am using google datastore to persist data as objects of a model class- 'zone' . This model has been updated with more parameters recently. When I deployed the new code, get calls on the existing 'zone' entities is resulting in an error. Existing zone entities do not have the newly added parameter(Marked in the zone class).
ERROR: Error in Service {} at com.tryout.cdapp.exceptions.handler.CNDApplicationExceptionHandler.(CNDApplicationExceptionHandler.java:30) on 2014-10-14 03:21:48,002
java.lang.NullPointerException
at com.google.appengine.datanucleus.scostore.FKListStore.getIndexPropertyName(FKListStore.java:965)
at com.google.appengine.datanucleus.scostore.FKListStore.getFilterPredicates(FKListStore.java:940)
at com.google.appengine.datanucleus.scostore.FKListStore.listIterator(FKListStore.java:383)
at com.google.appengine.datanucleus.scostore.FKListStore.listIterator(FKListStore.java:349)
at com.google.appengine.datanucleus.scostore.FKListStore.iterator(FKListStore.java:342)
at org.datanucleus.store.types.sco.backed.List.loadFromStore(List.java:304)
at org.datanucleus.store.types.sco.backed.List.initialise(List.java:253)
at org.datanucleus.store.types.sco.SCOUtils.createSCOWrapper(SCOUtils.java:253)
at org.datanucleus.store.types.sco.SCOUtils.newSCOInstance(SCOUtils.java:139)
at org.datanucleus.store.mapped.mapping.AbstractContainerMapping.replaceFieldWithWrapper(AbstractContainerMapping.java:396)
at org.datanucleus.store.mapped.mapping.AbstractContainerMapping.postFetch(AbstractContainerMapping.java:414)
at com.google.appengine.datanucleus.DatastorePersistenceHandler.fetchObject(DatastorePersistenceHandler.java:599)
at org.datanucleus.state.JDOStateManager.loadFieldsFromDatastore(JDOStateManager.java:1638)
at org.datanucleus.state.JDOStateManager.validate(JDOStateManager.java:3511)
at org.datanucleus.ObjectManagerImpl.findObject(ObjectManagerImpl.java:3379)
at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1722)
at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1740)
at com.tryout.cdapp.dao.impl.BaseDaoImpl.findById(BaseDaoImpl.java:103)
at com.tryout.cdapp.service.impl.ZoneServiceImpl.getZoneById(ZoneServiceImpl.java:55)
at com.tryout.cdapp.resource.ZoneResource.getById(ZoneResource.java:75)
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:45)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:280)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:234)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:221)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
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 org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
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 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.HttpConnection.handle(HttpConnection.java:404)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:438)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:445)
at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:220)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:309)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:301)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:442)
at java.lang.Thread.run(Thread.java:724)
This is the code in the Dao -
private final Class<T> persistentClass;
public BaseDaoImpl() {
persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public T findById(Serializable id) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
T t = pm.getObjectById(persistentClass, id);
t.toString();
return t;
} finally {
pm.close();
}
}
This is the code in service -
public Zone getZoneById(String id) {
Zone zone = zoneDao.findById(id);
return zone;
}
This is model class - 'Zone'
public class Zone implements Serializable {
private static final long serialVersionUID = 3946928960755099560L;
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String id;
@Persistent
private String name;
@Persistent
private String siteId;
@Persistent
private String orgId;
@Persistent(defaultFetchGroup = "true")
private List<LocationCoordinates> locationCoordinates;
@Persistent
private Date created;
@Persistent
private String description;
@Persistent
private String urlExtension;
@Persistent
private Integer timeSpentThreshold;
@Persistent
private Double tuningNumber;
@Persistent(defaultFetchGroup = "true")
private HashMap<String, String> zonePayload;
@Persistent(defaultFetchGroup = "true")
private List<ZoneSignalValue> zoneSignalValueList; //Newly Added
//Getters and Setters
}
How can I resolve this? Thanks in advance.
Upvotes: 5
Views: 285
Reputation: 429
I had the same issue, when tried reading newly added child entities to Old/existing Parents via JDO. Accessing the new child with Low-level Datastore API has no problem. This is problem with JDO as JDO does not model Schema-less Data models adequately in such scenarios. Two ways to solve this problem:
[As @Krishnalal suggested] If you want to stick with JDO reading then NEED to update all existing parent entities with newly added children. Just set them NULL for parents who donot have them already. Better do it running some script in Low-level Datastore APIs GET/PUT methods.
Read such children with the Low-level Datastore APIs GET methods. It will fetch you entity with full children tree if any else there would be no child property at all. So while converting entity to some JAVA Data Model say POJO, have some nullity or existence checks. You should be good to read such newly added children as null from old parent entities.
Feel free to ask for code help/sample if still not clear.
Upvotes: 0
Reputation: 487
You need to update the existing entities. You can refer this doc. https://cloud.google.com/appengine/articles/update_schema
Upvotes: 5