Deepak Sankar
Deepak Sankar

Reputation: 53

App-Engine throws NullPointerException on getByObjectId call of an entity that has been updated

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

Answers (2)

Pratap Singh
Pratap Singh

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:

  1. [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.

  2. 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

Krishnalal P
Krishnalal P

Reputation: 487

You need to update the existing entities. You can refer this doc. https://cloud.google.com/appengine/articles/update_schema

Upvotes: 5

Related Questions