views:

13

answers:

1

Is it possible to store a collection of embedded classes in Google App Engine (Java)? If so, how would I annotate it?

This is my class:

@PersistenceCapable
public class Employee
{
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    Key key;

    @Persistent(embeddedElement = "true")
    private List<ContactInfo> contactDetails = new ArrayList<ContactInfo>();

    public void addContactInfo(String streetAddress, String city)
    {
        this.contactDetails.add(new ContactInfo(streetAddress, city));
    }

    public List<ContactInfo> getContactDetails()
    {
        return this.contactDetails;
    }

    @PersistenceCapable
    @EmbeddedOnly
    public static class ContactInfo
    {
        @Persistent
        private String streetAddress;

        @Persistent
        private String city;

        public ContactInfo(String streetAddress, String city)
        {
            this.streetAddress = streetAddress;
            this.city = city;
        }

        public String getStreetAddress()
        {
            return this.streetAddress;
        }

        public String getCity()
        {
            return this.city;
        }
    }
}

Here is the test code:

// Create the employee object

Employee emp = new Employee();

// Add some contact details

emp.addContactInfo("123 Main Street", "Some City");
emp.addContactInfo("50 Blah Street", "Testville");

// Store the employee

PersistenceManager pm = PMF.get().getPersistenceManager();

try
{
    pm.makePersistent(emp);
} 
finally
{
    pm.close();
}

// Query the datastore for all employee objects

pm = PMF.get().getPersistenceManager();

Query query = pm.newQuery(Employee.class);

try
{
    List<Employee> employees = (List<Employee>) query.execute();

    // Iterate the employees

    for(Employee fetchedEmployee : employees)
    {
        // Output their contact details

        resp.getWriter().println(fetchedEmployee.getContactDetails());
    }
}
finally
{
    query.closeAll();
    pm.close();
}

The test code always outputs 'null'. Any suggestions?

I've tried annotating the contactDetails list as @Embedded, but the DataNucleus enhancer threw an exception. I've also tried adding defaultFetchGroup = "true" to the @Persistent annotation on the contactDetails list (in case it was a problem with fetching the data), but the output was still null. I've examined the employee object in the console and there's no evidence of any contact detail fields being stored on the object, nor are there any stand-alone ContactInfo objects in the datastore (not that I'd expect there to be, given they are embedded objects).

Is this even possible to do? I know that the fields of an embedded class are stored as properties on the entity, so I can see how field name conflicts might arise in a collection scneario, but the App Engine docs don't explicitly say it cannot be done.

A: 

With JDO you would do it as per the DataNucleus docs http://www.datanucleus.org/products/accessplatform_2_2/jdo/orm/embedded.html#Collection The example shows XML, but the annotation names are approximately equivalent.

Whether GAE/J's plugin supports this I couldn't say since it's Google's responsibility. Maybe try it?

DataNucleus