views:

442

answers:

3

I have the following java model class in AppEngine:

public class Xyz ... {
    @Persistent
    private Set<Long> uvw;
}

When saving an object Xyz with an empty set uvw in Java, I get a "null" field (as listed in the appengine datastore viewer). When I try to load the same object in python (through remote_api), as defined by the following python model class:

class Xys(db.Model):
    uvw = db.ListProperty(int)

I get a "BadValueError: Property uvw is required".

When saving another object of the same class in python with an empty uvw list, the datastore viewer print a "missing" field.

Apparently empty lists storage handling differs between Java and python and lead to "incompatible" objects.

Thus my question: Is there a way to, either:

  • force Java to store an empty list as a "missing" field,
  • force Python to gracefully accept a "null" list as an empty list when loading the object?

Or any other suggestion on how to handle empty list field in both languages.

Thanks for your answers!

A: 

The Java Set behavior is because Java's Collections are reference types, which default to being null.

To actually create an empty Set, declare it like this:

@Persistent
private Set<Long> uvw = new HashSet<Long>();

or using some other implementation of Set on the right side. HashSet is the most commonly used Set type, though. Other interesting set types are the two thread-safe Sets CopyOnWriteArraySet and ConcurrentSkipListSet; also the Ordered Set type LinkedHashSet and the Sorted Set type TreeSet.

R. Bemrose
Thanks, but when I save the object to the datastore the set is *empty*, not *null* (my code is not clear, I should have specified that before storing the object the set is an empty HashSet).The trick here is that the appengine datastore layer seems to convert empty set to "null" values when storing, and I don't see any control on this behavior.
lOranger
@IOranger: Ah, OK. I was going to delete this answer, but I'll leave it here so someone else doesn't come by later and say the same thing.
R. Bemrose
+1  A: 

I use the low-level java api, so perhaps what I am doing would be different. But before I save a collection-type data structure to the datastore, I convert it into something that the datastore naturally handles. This would include mainly Strings and ByteArrays.

It sounds like java app engine is interpreting the empty set as a null value. And python is not reading this null value correctly. You might try saving an empty set as the String value "empty set". And then have python check to see if the datastore holds that string value. If it does, it could allocate a new empty set, if not, it could read the property as a set.

DutrowLLC
+1  A: 

It should work if you assign a default value to your Python property:

uvw = db.ListProperty(int, default=[])
Claude Vedovini