title: Problems Mapping a List of Serializable Objects with JDO
body: <p>I have two classes Invoice and InvoiceItem. I would like Invoice to have a List of InvoiceItem Objets. I have red that the list must be of primitive or serializable objects. I have made InvoiceItem Serializable.</p>
  
  <p>Invoice.java looks like</p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.Date;
  import java.util.List;
  
  import javax.jdo.annotations.Column;
  import javax.jdo.annotations.Embedded;
  import javax.jdo.annotations.EmbeddedOnly;
  import javax.jdo.annotations.IdGeneratorStrategy;
  import javax.jdo.annotations.IdentityType;
  import javax.jdo.annotations.PersistenceCapable;
  import javax.jdo.annotations.Persistent;
  import javax.jdo.annotations.Element;
  import javax.jdo.annotations.PrimaryKey;
  
  import com.google.appengine.api.datastore.Key;
  import com.softamo.pelicamo.shared.InvoiceCompanyDTO;
  
  @PersistenceCapable(identityType = IdentityType.APPLICATION)
  public class Invoice {  
      @PrimaryKey
      @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
      private Long id;
  
      @Persistent
      private String number;
  
      @Persistent
      private Date date;
  
      @Persistent
      private List&lt;InvoiceItem&gt; items = new ArrayList&lt;InvoiceItem&gt;();
  
      public Invoice() {} 
  
      public Long getId() { return id; }
      public void setId(Long id) {this.id = id;}
  
      public String getNumber()           { return number;}
      public void setNumber(String invoiceNumber) { this.number = invoiceNumber;}
  
      public Date getDate()               { return date;}
      public void setDate(Date invoiceDate)       { this.date = invoiceDate;}
  
  
      public List&lt;InvoiceItem&gt; getItems()         { return items;}
      public void setItems(List&lt;InvoiceItem&gt; items)   { this.items = items;}
  
  }
  </code></pre>
  
  <p>and InvoiceItem.java looks like</p>
  
  <pre><code>import java.io.Serializable;
  import java.math.BigDecimal;
  import javax.jdo.annotations.PersistenceCapable;
  import javax.jdo.annotations.Persistent;
  
  @PersistenceCapable
  public class InvoiceItem implements Serializable {  
  
      @Persistent
      private BigDecimal amount;
  
      @Persistent
      private float quantity;
  
      public InvoiceItem() {}
  
      public BigDecimal getAmount()               {   return amount;}
      public void setAmount(BigDecimal amount)        { this.amount = amount;}
  
      public float getQuantity()              { return quantity;}
      public void setQuantity(float quantity)         { this.quantity = quantity;}
  }
  </code></pre>
  
  <p>I get the next error while running a JUnit test. </p>
  
  <pre><code>javax.jdo.JDOUserException: Attempt to handle persistence for object using datastore-identity yet StoreManager for this datastore doesn't support that identity type
      at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:375)
      at org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:674)
      at org.datanucleus.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:694)
      at com.softamo.pelicamo.server.InvoiceStore.add(InvoiceStore.java:23)
      at com.softamo.pelicamo.server.PopulateStorage.storeInvoices(PopulateStorage.java:58)
      at com.softamo.pelicamo.server.PopulateStorage.run(PopulateStorage.java:46)
      at com.softamo.pelicamo.server.InvoiceStoreTest.setUp(InvoiceStoreTest.java:44)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
      at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
  NestedThrowablesStackTrace:
  Attempt to handle persistence for object using datastore-identity yet StoreManager for this datastore doesn't support that identity type
  org.datanucleus.exceptions.NucleusUserException: Attempt to handle persistence for object using datastore-identity yet StoreManager for this datastore doesn't support that identity type
      at org.datanucleus.state.AbstractStateManager.&lt;init&gt;(AbstractStateManager.java:128)
      at org.datanucleus.state.JDOStateManagerImpl.&lt;init&gt;(JDOStateManagerImpl.java:215)
      at org.datanucleus.jdo.JDOAdapter.newStateManager(JDOAdapter.java:119)
      at org.datanucleus.state.StateManagerFactory.newStateManagerForPersistentNew(StateManagerFactory.java:150)
      at org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.java:1297)
      at org.datanucleus.sco.SCOUtils.validateObjectForWriting(SCOUtils.java:1476)
      at org.datanucleus.store.mapped.scostore.ElementContainerStore.validateElementForWriting(ElementContainerStore.java:380)
      at org.datanucleus.store.mapped.scostore.FKListStore.validateElementForWriting(FKListStore.java:609)
      at org.datanucleus.store.mapped.scostore.FKListStore.internalAdd(FKListStore.java:344)
      at org.datanucleus.store.appengine.DatastoreFKListStore.internalAdd(DatastoreFKListStore.java:146)
      at org.datanucleus.store.mapped.scostore.AbstractListStore.addAll(AbstractListStore.java:128)
      at org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(CollectionMapping.java:157)
      at org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostInsertMappingCallbacks(DatastoreRelationFieldManager.java:216)
      at org.datanucleus.store.appengine.DatastoreRelationFieldManager.access$200(DatastoreRelationFieldManager.java:47)
      at org.datanucleus.store.appengine.DatastoreRelationFieldManager$1.apply(DatastoreRelationFieldManager.java:115)
      at org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelations(DatastoreRelationFieldManager.java:80)
      at org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(DatastoreFieldManager.java:955)
      at org.datanucleus.store.appengine.DatastorePersistenceHandler.storeRelations(DatastorePersistenceHandler.java:527)
      at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProcess(DatastorePersistenceHandler.java:299)
      at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(DatastorePersistenceHandler.java:251)
      at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:235)
      at org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateManagerImpl.java:3185)
      at org.datanucleus.state.JDOStateManagerImpl.makePersistent(JDOStateManagerImpl.java:3161)
      at org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.java:1298)
      at org.datanucleus.ObjectManagerImpl.persistObject(ObjectManagerImpl.java:1175)
      at org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:669)
      at org.datanucleus.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:694)
      at com.softamo.pelicamo.server.InvoiceStore.add(InvoiceStore.java:23)
      at com.softamo.pelicamo.server.PopulateStorage.storeInvoices(PopulateStorage.java:58)
      at com.softamo.pelicamo.server.PopulateStorage.run(PopulateStorage.java:46)
      at com.softamo.pelicamo.server.InvoiceStoreTest.setUp(InvoiceStoreTest.java:44)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
      at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
  </code></pre>
  
  <p>Moreover, when I try to store an invoice with a list of items through my app. In the development console I can see that items are not persisted to any field while the rest of the invoice class properties are stored properly.</p>
  
  <p>Does anyone know what I am doing wrong? </p>
  
  <h2>Solution</h2>
  
  <p>As pointed in the answers, the error says that the InvoiceItem class was missing a primaryKey. I tried with: </p>
  
  <pre><code>@PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Long id;
  </code></pre>
  
  <p>But I was getting</p>
  
  <pre><code>javax.jdo.JDOFatalUserException: Error in meta-data for InvoiceItem.id: Cannot have a java.lang.Long primary key and be a child object (owning field is Invoice.items).
  </code></pre>
  
  <p>In <a href="https://stackoverflow.com/questions/2063467/persist-list-of-objects">persist list of objets</a>, <a href="https://stackoverflow.com/users/74057/aldrin">@aldrin</a> pointed that </p>
  
  <blockquote>
    <p>For child classes the primary key has
    to be a
    com.google.appengine.api.datastore.Key
    value (or encoded as a string) <a href="http://code.google.com/appengine/docs/java/datastore/creatinggettinganddeletingdata.html#Keys" rel="nofollow noreferrer">see</a></p>
  </blockquote>
  
  <p>So, I tried with Key. It worked. </p>
  
  <pre><code>@PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key id; 
  </code></pre>