Generate Automatic Id IdGeneratorStrategy
Asked Answered
P

3

8

I'm using Goole App Engine to Build my REST API, I've already marked my class as PersistenceCapable and also i got defined my @PrimaryKey and also marked as @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY), also i've already EndPoints generated. but when i type in the terminal window a curl command to insert a new entity or registry it doesn't work. this is the code:

 @PersistenceCapable(identityType = IdentityType.APPLICATION)
 class Student{
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long     id;
    private String   studentName;
    ....
    ....
    ....
}

this is the curl command and response from my local server. when i try to insert a new entity

curl -H 'Content-Type: application/json' -d'{"studentName": "myname"}' htto://localhost:8889/_ah/api/utp/v1/student

and this is the response from the local server.

"error" : {
"message" : "javax.jdo.JDOFatalInternalException: El valor de llave dado para construir una identidad de SingleFieldIdentity de tipo \"class javax.jdo.identity.LongIdentity\" para la clase \"class com.alex.wserver.Student\" es nulo.\nNestedThrowables:\norg.datanucleus.exceptions.NucleusException: El valor de llave dado para construir una identidad de SingleFieldIdentity de tipo \"class javax.jdo.identity.LongIdentity\" para la clase \"class com.alex.wserver.Student\" es nulo."

i've been thinking that id was automatically generated an inserted. but that isn't happening here. Unlike of insert an id together


  1. are my class wrong?
  2. are my POST/json request Ok?

Thanks in advance.

Proletariat answered 20/2, 2013 at 2:56 Comment(4)
and the log says what? (also I can't read those hieroglyphics that you posted above; I see no Java persistence code there either, like pm.makePersistent).Parnell
You could have pasted directly the code snippets. The pictures are kinda small and hard to figure out.Nab
I've already changed the images by code snipped... sorry for bad images...Proletariat
this is the example which i've followed youtube.com/watch?v=v9TG7OzsZqQProletariat
P
8

I think the that i've found the solution. It seems that every endpoint generated by Google App Engine(GAE) framework has a simple method which check every time that someone is trying to insert or update and a persistant instance, so the fact was every time that i've tried to insert a new student using curl/json without specify de new id for the instance it displayed a error message like this one:

    "error": {
      "message": javax.jdo.JDOFatalInternalException: The key value passed to construct a
      SingleFieldIdentity type \ class javax.jdo.identity.LongIdentity \ for class \ class com.alex.wserver.Student \ is null. \ nNestedThrowables: \ norg.datanucleus.exceptions.NucleusException: the key value passed to construct a SingleFieldIdentity type \ class javax.jdo.identity.LongIdentity \ for class \ class com.alex . wserver.Student \ is null.

so i've solve the problem editing my endpoint class by checking if the new object(sent by curl command and wrapped json format) has a not null id value before even check if the object has been stored before with this code:

        if(student.getKey() != null){
            if (containsStudent(student)) {
                throw new EntityExistsException("Object already exists");
            }
        }
        mgr.makePersistent(student);

As far i haven't seen any documentation which can clarify that aspect for me. Also i add, i've spend a lot of time reading the documentation on GAE before trying to figure out what's been happening.


All that made me think that maybe just maybe the GAE documentation is not up to date or probably i havent search enough, so if someone know about. please let me know it and grow the common knowledge. thanks @DataNucleus.

NOTE: "This fork that i've made should not be taked as correct answer, it could be take you to unexpected behavior of your app."

Proletariat answered 22/2, 2013 at 0:12 Comment(4)
+1 You saved my day! This can be considered a bug of GPE which generates the undesirable code for Google Cloud Endpoints.Stephanstephana
hello @ToyHunter, i've made some research and i've found a better solution. now i'm using a static Iterator Object which contains a range of keys. so every time i POST a new entity i get the new Key for the new object. i wrote a private static method inside of Endpoint class which initialize the iterator, so when i POST a new object the iterator get a new key and i just assign it to the new object and persist it.here some referenceProletariat
+1 Your approach is definitely helpful from the perspective that ones may want to preserve ids through data migration. Just wondering why not all of these issues are taken care by App Engine already.Stephanstephana
It would be nice if @Parnell could give his opinion.Bore
C
1

The problem lies in the contains method of the endpoint that was generated automatically. The exception being thrown is javax.jdo.JDOFatalInternalException when the id is null and the method catches the exception javax.jdo.JDOObjectNotFoundException.

The exception is never caught and you get the error. I don't if it's a bug or what, but after updating the catch statement to catch both, the problem was solved.

Hope it helps!

Crossroad answered 15/7, 2014 at 19:11 Comment(0)
W
0

As remarked in the answer by AlexSanchez, the generated endpoint code expects the primary key already set on inserting new identities.

While some may view this as a bug, others may view as a feature, because it requires the client to generate the key somehow (e.g. by creating a random uuid when the key type is String). This way, the client can create a full graph of entities even while offline and upload them to the server once online.

(I think the Spine framework is an example for this idea: http://spinejs.com/.)

Wildebeest answered 26/5, 2013 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.