Search code examples
google-app-enginejdodatanucleus

GooglePlugin FKListStore NullPointerException at AppEngine JDO many-to-one relationship


I am trying to put a kind of entities in the same entity group than its parent. I have read some post here but no one seems to have the same problem so I have to be doing something wrong (but I am not able to see it) .

I got Brands (father) and Stores (sons), my issue is when trying to add an Store to a Brand where, for some reason, I am getting a weird NullPointerException.

Caused by: java.lang.NullPointerException
    at com.google.appengine.datanucleus.scostore.FKListStore$3.fetchFields(FKListStore.java:1093)
...

Here are the classes involved and the code adding the Store to the father:

@PersistenceCapable
public class Brand {

   @PrimaryKey
   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
   @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
   protected String key;

    @Persistent
    @Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
    protected Long keyId;

   @Persistent(defaultFetchGroup = "false")
   private List<Store> stores;
}

And this is the Store:

@PersistenceCapable
public class Store {
   @PrimaryKey
   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
   @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
   protected String key;

   @Persistent
   @Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
   private Long keyId;

   @Persistent(mappedBy = "stores") 
   protected BrandEntity brand;

}

A Brand has been created at some point and now I want to add an Store to the same entity group. Nothing strange:

public static StoreEntity addStore(String brandKey, Store store) {
   PersistenceManager mgr = getPersistenceManager();
   try { 
      BrandEntity brand = mgr.getObjectById(BrandEntity.class, brandKey);

      if (brand != null){
          brand.getStores(); //feth to retrieve collection from datastore           

          //add relationship
          newStore.setBrand(brand);
          List<StoreEntity> aux = brand.getStores(); //list is lazily fetched here
          if (aux == null)
             aux = new ArrayList<Store>();  //maybe is the first one ()            

          /*-- Nullpointer next line --*/
          aux.add(newStore);
          /*--NullPointer last line --*/

          brand.setStores(aux); 
          brand = mgr.makePersistent(brand);
          return store;
      }
   } finally{
      mgr.close();
   }

   return null;
}

I am aware that at the appengine documentation example the "mappedBy="nameOf theField" is at the parent (Brand in my case) instead of putting it at the son (Store) but I want the Store to be at the same Entity group than Brand.

So, if anyone has any suggestion I will really apreciate it.


Solution

  • Thanks to @Danaucleus for solving my issue. My mistake was just that I was setting the BrandEntity as parent of the Store manually.

    store.addBrand(theBrand); //this should not be done
    brand.getStores().add(store);
    

    but this parent relationship is automatically filled when doing this:

    brand.getStores().add(store);
    

    Also, as I wanted a bidirectional relationship, I have to put the "mappedBy" annotation on both sides of the relationship, this at BrandEntity class (parent):

    @Persistent (mappedBy="brand")
    private List<StoreEntity> stores;
    

    This at StoreEntity class (child)

    @persistent (mappedBy="stores"
    BrandEntity brand;
    

    So I was definitively missing something stupid but it is true that the NullPointerException I was getting was unclear and unhelpful.