[appengine-java] Re: ArrayIndexOutOfBoundsException when trying to persist an ArrayList of Objects which utilise inheritence

2011-08-09 Thread Rolf Aden
The only supported inheritance mapping strategy for polymorphic
relationships is currently for
JDO) new-table for the base class and superclass-table for all
subclasses
JPA) SingleTable.

This means, everything in the inheritance hierarchy ends up in one
entity kind, as you have noticed.  Since we have an owned
relationship, the entities (Car) get an ancestor key of the entity
owning the relationship (Person). And the owning entity gets a
property (cars) with all the keys of the entities in the list. And to
get the java classes for the stored entities, when reading the data
back, we have the discriminator.

Example:
One Person
Entity [Person(1)]: (kind is “Person”)
cars = [Person(1)/Car(2), Person(1)/Car(3)]
name = Former F1 Champion


with two Cars
Entity [Person(1)/Car(2)]:  (ancestor key Person(1), kind is “Car”)
modelName = Ferrari
DISCRIMINATOR = org.datanucleus.test.Model
cars_INTEGER_IDX = 0


Entity [Person(1)/Car(3)]: (ancestor key Person(1), kind is “Car”)
anotherModelName = Mercedes
DISCRIMINATOR = org.datanucleus.test.AnotherModel
cars_INTEGER_IDX = 1


Let's assume we would allow splitting the data of the elements of a
relationship over more than one entity kind. To query the data store,
with the low level Datastore API, to get the data for the cars owned
by a person, you have basically the following options to formulate the
queries (http://code.google.com/intl/de-DE/appengine/docs/java/
datastore/queries.html):
1) with a kind (e.g. Car, Model, AnotherModel, ...) and an ancestor
key (key of the person owning the cars)
= reading all Cars for a person means you have to execute a query
for every entity kind involved in the inheritance hierarchy (would be
five in your case) and then merge the results
2) no kind and no ancestor, but a filter on the entity keys in the
list property (person.cars)
= this would require a query with an IN filter, but the IN-queries
are translated into multiple Equal-queries (http://gae-java-
persistence.blogspot.com/2009/12/queries-with-and-in-filters.html),
this in turn leads to a query for every entity in the list.
3) no kind but an ancestor key
= this could also return entities not belonging to the relationship
cars but to an another relationship of person(e.g. addresses). You
would read too many entities and you would have to filter out all
entities not belonging to this relationship.
2) no kind and no ancestor
= this would require only one query, but the query would return all
entities from your data store and you have to filter them in memory, I
guess this is totally out of the question.

The probably most performant solution here is to forbid splitting up
the data of a collection element over multiple entity kinds and
execute one query with a kind and an ancestor. But there is catch. You
cannot have two relationships with the same element class (at least
not at the moment). This problem could be solved easily, if the
entities for the collection elements would get another property which
says to which relationship it belongs. But in my opinion, it would be
even better, if the low level Datastore API would support (without the
need to split the query) kindless queries with an ancestor key and an
IN filter on “subkeys” of the ancestor key. This should be performant
since, as I understand it, all the data of one entity group resides in
one bigtable row.

I hope this explanation makes it easier for you to see all your
different cars stored in one entity kind. And if you want to save a
little space, you can take advantage of a discriminator map, and
annotate your classes the following way:

@PersistenceCapable()
@Discriminator(column = D, strategy =
DiscriminatorStrategy.VALUE_MAP)
public abstract class Car { … }

@PersistenceCapable
@Discriminator(value = M)
public class Model extends Car { …}

Rolf


On 8 Aug., 20:43, mscwd01 mscw...@gmail.com wrote:
 This worked nicely!

 One question I do have is, I noticed App Engine does not store Model
 kinds it instead stores Car kinds with a String DISCRIMINATOR
 property that stores what type of Class it is. Is it not possible to
 store Model entities? I actually have 5 Classes which extend Car and
 would have preferred to store an entity for each rather than have a
 Car kind comprising of each different class.

 Thanks for the help so far though!

 On Aug 8, 10:44 am, Rolf Aden mail.rolf.a...@googlemail.com wrote:







  It seems you are not using the latest sdk version (be something pre
  1.5.1?).
  As of release 1.5.1 polymorphic relationships are supported for the
  default inheritance strategy in JDO (new-table for the base class, and
  superclass-table for all subclasses) and JPA SingleTable. You may want
  to change Car to

  @PersistenceCapable
  @Discriminator(column = DISCRIMINATOR)
  public abstract class Car {
  

  }

  and keep Model

  @PersistenceCapable
  public class Model extends Car {
  ...

  }

  Rolf

  

[appengine-java] Re: ArrayIndexOutOfBoundsException when trying to persist an ArrayList of Objects which utilise inheritence

2011-08-08 Thread Rolf Aden
It seems you are not using the latest sdk version (be something pre
1.5.1?).
As of release 1.5.1 polymorphic relationships are supported for the
default inheritance strategy in JDO (new-table for the base class, and
superclass-table for all subclasses) and JPA SingleTable. You may want
to change Car to

@PersistenceCapable
@Discriminator(column = DISCRIMINATOR)
public abstract class Car {

}

and keep Model

@PersistenceCapable
public class Model extends Car {
...
}

Rolf


On 8 Aug., 01:35, mscwd01 mscw...@gmail.com wrote:
 Hey,

 I have 3 classes: Person, Car and Model.

 Person has an ArrayList property defined:
 ListCar cars;

 Car is an abstract class which class Model extends, I.e.

 @PersistenceCapable
 @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
 public abstract class Car {

   @PrimaryKey
   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
   protected Key key;

   public Car() {
   }

 }

 Model extends Car:

 @PersistenceCapable
 public class Model extends Car {

   public Model() {
   }

 }

 I load a Person object and create a new Car object, I.e.

 Person personObj = pm.getObjectById(Person.class, key);
 Car newCar = new Model();

 I then try to persist the new Car by adding it to the cars property
 in the Person Class, I.e.

 personObj.getCars().add(newCar);

 However, when I try this App Engine throws the following exception:

 java.lang.ArrayIndexOutOfBoundsException: 0
         at
 org.datanucleus.store.mapped.scostore.FKListStore.init(FKListStore.java:
 133)
         at
 org.datanucleus.store.appengine.DatastoreFKListStore.init(DatastoreFKList 
 Store.java:
 41)
         at
 org.datanucleus.store.appengine.DatastoreManager.newFKListStore(DatastoreMa 
 nager.java:
 528)
         at
 org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForCollectio 
 n(MappedStoreManager.java:
 729)
         at
 org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForField(Map 
 pedStoreManager.java:
 646)
         at org.datanucleus.sco.backed.List.init(List.java:104)
         at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
 Method)
         at
 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAcce 
 ssorImpl.java:
 39)
         at
 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstru 
 ctorAccessorImpl.java:
 27)
         at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
         at
 com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(R 
 untime.java:
 112)
         at
 com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Ru 
 ntime.java:
 120)
         at org.datanucleus.util.ClassUtils.newInstance(ClassUtils.java:94)
         at org.datanucleus.sco.SCOUtils.newSCOInstance(SCOUtils.java:164)
         at
 org.datanucleus.store.mapped.mapping.AbstractContainerMapping.replaceFieldW 
 ithWrapper(AbstractContainerMapping.java:
 426)
         at
 org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(Collectio 
 nMapping.java:
 165)
         at
 org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostInsert 
 MappingCallbacks(DatastoreRelationFieldManager.java:
 217)
         at
 org.datanucleus.store.appengine.DatastoreRelationFieldManager.access
 $200(DatastoreRelationFieldManager.java:48)
         at org.datanucleus.store.appengine.DatastoreRelationFieldManager
 $1.apply(DatastoreRelationFieldManager.java:116)
         at
 org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelation 
 s(DatastoreRelationFieldManager.java:
 81)
         at
 org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(Datast 
 oreFieldManager.java:
 955)
         at
 org.datanucleus.store.appengine.DatastorePersistenceHandler.storeRelations( 
 DatastorePersistenceHandler.java:
 546)
         at
 org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProce 
 ss(DatastorePersistenceHandler.java:
 304)
         at
 org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(D 
 atastorePersistenceHandler.java:
 256)
         at
 org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(Da 
 tastorePersistenceHandler.java:
 240)
         at
 org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateMa 
 nagerImpl.java:
 3185)
         at
 org.datanucleus.state.JDOStateManagerImpl.makePersistent(JDOStateManagerImp 
 l.java:
 3161)
         at
 org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.j 
 ava:
 1298)
         at
 org.datanucleus.ObjectManagerImpl.persistObject(ObjectManagerImpl.java:
 1170)
         at
 org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceM 
 anager.java:
 669)
         at
 org.datanucleus.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceMana 
 ger.java:
 694)

 This sounds much like a similar question that was raised 
 

[appengine-java] Re: ArrayIndexOutOfBoundsException when trying to persist an ArrayList of Objects which utilise inheritence

2011-08-08 Thread mscwd01
This sounds like it could be the issue, I'll go ahead and upgrade to
the latest SDK tonight and see how I get on.

Thanks Rolf

On Aug 8, 10:44 am, Rolf Aden mail.rolf.a...@googlemail.com wrote:
 It seems you are not using the latest sdk version (be something pre
 1.5.1?).
 As of release 1.5.1 polymorphic relationships are supported for the
 default inheritance strategy in JDO (new-table for the base class, and
 superclass-table for all subclasses) and JPA SingleTable. You may want
 to change Car to

 @PersistenceCapable
 @Discriminator(column = DISCRIMINATOR)
 public abstract class Car {
 

 }

 and keep Model

 @PersistenceCapable
 public class Model extends Car {
 ...

 }

 Rolf

 On 8 Aug., 01:35, mscwd01 mscw...@gmail.com wrote:







  Hey,

  I have 3 classes: Person, Car and Model.

  Person has an ArrayList property defined:
  ListCar cars;

  Car is an abstract class which class Model extends, I.e.

  @PersistenceCapable
  @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
  public abstract class Car {

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    protected Key key;

    public Car() {
    }

  }

  Model extends Car:

  @PersistenceCapable
  public class Model extends Car {

    public Model() {
    }

  }

  I load a Person object and create a new Car object, I.e.

  Person personObj = pm.getObjectById(Person.class, key);
  Car newCar = new Model();

  I then try to persist the new Car by adding it to the cars property
  in the Person Class, I.e.

  personObj.getCars().add(newCar);

  However, when I try this App Engine throws the following exception:

  java.lang.ArrayIndexOutOfBoundsException: 0
          at
  org.datanucleus.store.mapped.scostore.FKListStore.init(FKListStore.java:
  133)
          at
  org.datanucleus.store.appengine.DatastoreFKListStore.init(DatastoreFKList 
  Store.java:
  41)
          at
  org.datanucleus.store.appengine.DatastoreManager.newFKListStore(DatastoreMa 
  nager.java:
  528)
          at
  org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForCollectio 
  n(MappedStoreManager.java:
  729)
          at
  org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForField(Map 
  pedStoreManager.java:
  646)
          at org.datanucleus.sco.backed.List.init(List.java:104)
          at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
  Method)
          at
  sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAcce 
  ssorImpl.java:
  39)
          at
  sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstru 
  ctorAccessorImpl.java:
  27)
          at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
          at
  com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(R 
  untime.java:
  112)
          at
  com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Ru 
  ntime.java:
  120)
          at org.datanucleus.util.ClassUtils.newInstance(ClassUtils.java:94)
          at org.datanucleus.sco.SCOUtils.newSCOInstance(SCOUtils.java:164)
          at
  org.datanucleus.store.mapped.mapping.AbstractContainerMapping.replaceFieldW 
  ithWrapper(AbstractContainerMapping.java:
  426)
          at
  org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(Collectio 
  nMapping.java:
  165)
          at
  org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostInsert 
  MappingCallbacks(DatastoreRelationFieldManager.java:
  217)
          at
  org.datanucleus.store.appengine.DatastoreRelationFieldManager.access
  $200(DatastoreRelationFieldManager.java:48)
          at org.datanucleus.store.appengine.DatastoreRelationFieldManager
  $1.apply(DatastoreRelationFieldManager.java:116)
          at
  org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelation 
  s(DatastoreRelationFieldManager.java:
  81)
          at
  org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(Datast 
  oreFieldManager.java:
  955)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.storeRelations( 
  DatastorePersistenceHandler.java:
  546)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProce 
  ss(DatastorePersistenceHandler.java:
  304)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(D 
  atastorePersistenceHandler.java:
  256)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(Da 
  tastorePersistenceHandler.java:
  240)
          at
  org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateMa 
  nagerImpl.java:
  3185)
          at
  org.datanucleus.state.JDOStateManagerImpl.makePersistent(JDOStateManagerImp 
  l.java:
  3161)
          at
  org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.j 
  ava:
  1298)
          at
  org.datanucleus.ObjectManagerImpl.persistObject(ObjectManagerImpl.java:
  

[appengine-java] Re: ArrayIndexOutOfBoundsException when trying to persist an ArrayList of Objects which utilise inheritence

2011-08-08 Thread mscwd01
This worked nicely!

One question I do have is, I noticed App Engine does not store Model
kinds it instead stores Car kinds with a String DISCRIMINATOR
property that stores what type of Class it is. Is it not possible to
store Model entities? I actually have 5 Classes which extend Car and
would have preferred to store an entity for each rather than have a
Car kind comprising of each different class.

Thanks for the help so far though!



On Aug 8, 10:44 am, Rolf Aden mail.rolf.a...@googlemail.com wrote:
 It seems you are not using the latest sdk version (be something pre
 1.5.1?).
 As of release 1.5.1 polymorphic relationships are supported for the
 default inheritance strategy in JDO (new-table for the base class, and
 superclass-table for all subclasses) and JPA SingleTable. You may want
 to change Car to

 @PersistenceCapable
 @Discriminator(column = DISCRIMINATOR)
 public abstract class Car {
 

 }

 and keep Model

 @PersistenceCapable
 public class Model extends Car {
 ...

 }

 Rolf

 On 8 Aug., 01:35, mscwd01 mscw...@gmail.com wrote:







  Hey,

  I have 3 classes: Person, Car and Model.

  Person has an ArrayList property defined:
  ListCar cars;

  Car is an abstract class which class Model extends, I.e.

  @PersistenceCapable
  @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
  public abstract class Car {

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    protected Key key;

    public Car() {
    }

  }

  Model extends Car:

  @PersistenceCapable
  public class Model extends Car {

    public Model() {
    }

  }

  I load a Person object and create a new Car object, I.e.

  Person personObj = pm.getObjectById(Person.class, key);
  Car newCar = new Model();

  I then try to persist the new Car by adding it to the cars property
  in the Person Class, I.e.

  personObj.getCars().add(newCar);

  However, when I try this App Engine throws the following exception:

  java.lang.ArrayIndexOutOfBoundsException: 0
          at
  org.datanucleus.store.mapped.scostore.FKListStore.init(FKListStore.java:
  133)
          at
  org.datanucleus.store.appengine.DatastoreFKListStore.init(DatastoreFKList 
  Store.java:
  41)
          at
  org.datanucleus.store.appengine.DatastoreManager.newFKListStore(DatastoreMa 
  nager.java:
  528)
          at
  org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForCollectio 
  n(MappedStoreManager.java:
  729)
          at
  org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForField(Map 
  pedStoreManager.java:
  646)
          at org.datanucleus.sco.backed.List.init(List.java:104)
          at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
  Method)
          at
  sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAcce 
  ssorImpl.java:
  39)
          at
  sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstru 
  ctorAccessorImpl.java:
  27)
          at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
          at
  com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(R 
  untime.java:
  112)
          at
  com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Ru 
  ntime.java:
  120)
          at org.datanucleus.util.ClassUtils.newInstance(ClassUtils.java:94)
          at org.datanucleus.sco.SCOUtils.newSCOInstance(SCOUtils.java:164)
          at
  org.datanucleus.store.mapped.mapping.AbstractContainerMapping.replaceFieldW 
  ithWrapper(AbstractContainerMapping.java:
  426)
          at
  org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(Collectio 
  nMapping.java:
  165)
          at
  org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostInsert 
  MappingCallbacks(DatastoreRelationFieldManager.java:
  217)
          at
  org.datanucleus.store.appengine.DatastoreRelationFieldManager.access
  $200(DatastoreRelationFieldManager.java:48)
          at org.datanucleus.store.appengine.DatastoreRelationFieldManager
  $1.apply(DatastoreRelationFieldManager.java:116)
          at
  org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelation 
  s(DatastoreRelationFieldManager.java:
  81)
          at
  org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(Datast 
  oreFieldManager.java:
  955)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.storeRelations( 
  DatastorePersistenceHandler.java:
  546)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProce 
  ss(DatastorePersistenceHandler.java:
  304)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(D 
  atastorePersistenceHandler.java:
  256)
          at
  org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(Da 
  tastorePersistenceHandler.java:
  240)
          at
  org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateMa 
  nagerImpl.java: