asolfre / objectify-appengine

Automatically exported from code.google.com/p/objectify-appengine
MIT License
0 stars 0 forks source link

"id cannot be zero" when using @Id long (as opposed to @Id Long) #113

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
There seems to be a problem with @Id fields declared as 'long' in Objectify 
3.1b1 / GAE 1.5.5.

Steps to reproduce:
1. Create a class with an @Id field declared as 'long' (the basic type, not the 
wrapper type 'Long')
   class MyEntity {
      @Id long id;
   }
2. Create an instance of this entity.
3. Put the entity with Objectify.put().

Expected output:
The entity should be put in the datastore.

Actual output:
An IllegalArgumentException with the message "id cannot be zero" is thrown with 
the following stack trace:

java.lang.IllegalArgumentException: id cannot be zero
    at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:44)
    at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:31)
    at com.googlecode.objectify.impl.ConcreteEntityMetadata.initEntity(ConcreteEntityMetadata.java:295)
    at com.googlecode.objectify.impl.ConcreteEntityMetadata.toEntity(ConcreteEntityMetadata.java:217)
    at com.googlecode.objectify.impl.AsyncObjectifyImpl.put(AsyncObjectifyImpl.java:252)
    at com.googlecode.objectify.impl.AsyncObjectifyImpl.put(AsyncObjectifyImpl.java:229)
    at com.googlecode.objectify.impl.ObjectifyImpl.put(ObjectifyImpl.java:126)

I went to investigate this issue and I found that when the declaration is 
changed to:
   class MyEntity {
      @Id Long id; // note the capital L
   }
the entity is correctly put into the datastore.

I have managed to find the cause of this problem inside the initEntity method 
of ConcreteEntityMetaData. Lines 287-291:
    if (this.idField != null)
    {
        Long id = (Long)this.idField.get(obj);  // possibly null
        if (id != null)
        {
When the idField points to a field of the basic type 'long' with the value '0', 
the value of 'id' becomes equal to 'new Long(0)'. The problem is that this DOES 
NOT equal null!

To fix this, the condition in the if-test needs to be changed:
    if (this.idField != null)
    {
        Long id = (Long)this.idField.get(obj);  // possibly null
        if (id != null && id != 0)
        {

I don't have a .patch file for this (not sure how to configure the Objectify 
source in Eclipse), but I think it's pretty obvious.

Thank you for your attention.

Original issue reported on code.google.com by mattias....@gmail.com on 9 Nov 2011 at 4:49

GoogleCodeExporter commented 9 years ago
Damnit, I should have investigated further. This has already been reported in 
issue 96. My apologies.

Original comment by mattias....@gmail.com on 9 Nov 2011 at 4:57

GoogleCodeExporter commented 9 years ago
This is an explicit (and well-documented) design decision.

long (lowercase) id fields are *never* autogenerated.
Long (uppercase) id fields are autogenerated when they are null.
0 is disallowed as an id by the datastore.

Use lowercase-long id fields when you have integer natural keys.  Use 
uppercase-Long when you have synthetic keys.  If we allowed lowercase-long id 
fields to autogenerate, any programming mistake that put an uninitialized 0 in 
the database would trigger the allocator and potentially overwrite an existing 
natural key.

Issue 96 is specifically about Scala integration.

Original comment by lhori...@gmail.com on 9 Nov 2011 at 7:22

GoogleCodeExporter commented 9 years ago
Double damnit, I can't believe I missed that on the wiki. I feel like an idiot 
right now. :-P

Thanks for responding though. :-)

Original comment by mattias....@gmail.com on 9 Nov 2011 at 10:57

GoogleCodeExporter commented 9 years ago
No prob :-)

Original comment by lhori...@gmail.com on 9 Nov 2011 at 11:07

GoogleCodeExporter commented 9 years ago
Which page in Objectify's documentation contains this information? I cannot 
find this anywhere except in this Google Code issue page.

Original comment by ecb0...@gmail.com on 26 Dec 2012 at 9:24

GoogleCodeExporter commented 9 years ago
https://code.google.com/p/objectify-appengine/wiki/Entities#The_Basics

Original comment by lhori...@gmail.com on 27 Dec 2012 at 12:56