2013-02-20 10 views
8

I Goole App Engine bin mit meiner REST API zu bauen, habe ich markiert bereits meine Klasse als PersistenceCapable und auch bekam ich meine @PrimaryKey und auch als @Persistent (valueStrategy markiert definiert = IdGeneratorStrategy.IDENTITY), auch ich habe schon EndPoints generiert. aber wenn ich das terminal-Fenster ein curl-Befehl einfüge, um eine neue Entität oder Registrierung einzufügen, funktioniert es nicht. Dies ist der Code:generieren Automatische Id IdGeneratorStrategy

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

dies ist der curl Befehl und die Antwort von meinem lokalen Server. wenn ich versuche, eine neue Einheit

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

und dies ist die Antwort von dem lokalen Server einzufügen.

Ich habe gedacht, dass ID automatisch erstellt wurde eingefügt. aber das passiert hier nicht. Im Gegensatz zu der einfügen einer ID zusammen


  1. ist meine Klasse falsch?
  2. sind meine POST/JSON Anfrage Ok?

Vielen Dank im Voraus.

+0

und das Protokoll sagt was? (Ich kann auch nicht die Hieroglyphen lesen, die Sie oben gepostet haben; ich sehe dort auch keinen Java-Persistenz-Code, wie pm.makePersistent). – DataNucleus

+0

Sie hätten die Code-Snippets direkt einfügen können. Die Bilder sind ein bisschen klein und schwer zu verstehen. –

+0

Ich habe bereits die Bilder durch Code-Schnipsel geändert ... Entschuldigung für schlechte Bilder ... – AlexSanchez

Antwort

8

Ich denke, dass ich die Lösung gefunden habe. Es scheint, dass jeder von Google App Engine (GAE) generierte Endpunkt über eine einfache Methode verfügt, die jedes Mal prüft, wenn jemand versucht, eine persistente Instanz einzufügen oder zu aktualisieren, also jedes Mal, wenn ich versucht habe, eine neue Instanz einzufügen ohne angeben Schüler curl/json für die Instanz de neue ID mit angezeigt eine Fehlermeldung wie diese:

"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 habe ich, wenn das neue Objekt, das Problem der Bearbeitung meiner Endpunkt Klasse lösen, indem geprüft (send by curl command und wrapped json format) hat einen not-id-Wert, bevor Sie mit diesem code prüfen, ob das Objekt schon einmal gespeichert wurde:

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

Soweit ich keine Dokumentation gesehen habe, die diesen Aspekt für mich klären kann. Auch ich füge hinzu, ich habe eine Menge Zeit damit verbracht, die Dokumentation auf GAE zu lesen, bevor ich versuche, herauszufinden, was passiert ist.


Alles, was ich denken ließ, dass vielleicht nur vielleicht die GAE-Dokumentation ist nicht auf dem neuesten Stand oder wahrscheinlich havent ich genug suchen, so dass, wenn jemand wissen. lass es mich wissen und das allgemeine Wissen wachsen. Danke @DataNucleus.

HINWEIS: "Diese Gabel, die ich gemacht habe, sollte nicht als richtige Antwort genommen werden, es könnte Sie zu unerwartetem Verhalten Ihrer App führen."

+1

+1 Sie rettete meinen Tag! Dies kann als ein Fehler von GPE angesehen werden, der unerwünschten Code für Google Cloud Endpoints generiert. –

+2

Hallo @ToyHunter, ich habe etwas Forschung gemacht und ich habe eine bessere Lösung gefunden. Jetzt benutze ich ein statisches Iterator-Objekt, das eine Reihe von Schlüsseln enthält. Also jedes Mal, wenn ich eine neue Entity POST, bekomme ich den neuen Key für das neue Objekt. Ich habe eine private statische Methode innerhalb der Endpoint-Klasse geschrieben, die den Iterator initialisiert. Wenn ich also ein neues Objekt POST eintrage, erhält der Iterator einen neuen Schlüssel und ich weise ihn dem neuen Objekt zu und behalte es dort.hier [Referenz] (https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyRange) – AlexSanchez

+1

+1 Ihr Ansatz ist auf jeden Fall hilfreich, wenn Sie die IDs durch Datenmigration beibehalten möchten. Ich frage mich nur, warum all diese Probleme nicht schon von App Engine beachtet werden. –

0

Wie in der Antwort von AlexSanchez angemerkt, erwartet der generierte Endpunktcode, dass der Primärschlüssel bereits beim Einfügen neuer Identitäten gesetzt ist.

Während einige dies als Fehler betrachten, können andere dies als Feature betrachten, da der Client den Schlüssel irgendwie generieren muss (z. B. durch Erstellen einer zufälligen Uuid, wenn der Schlüsseltyp String ist). Auf diese Weise kann der Client auch offline einen vollständigen Graphen von Entitäten erstellen und diese online auf den Server hochladen.

(ich glaube, der Spine-Framework ist ein Beispiel für diese Idee. http://spinejs.com/)

1

Das Problem liegt in der Methode des Endpunkts enthält, die automatisch generiert wurden. Die ausgelöste Ausnahme ist javax.jdo.JDOFatalInternalException, wenn die ID null ist und die Methode die Ausnahme javax.jdo.JDOObjectNotFoundException abfängt.

Die Ausnahme wird nie abgefangen und Sie erhalten den Fehler. Ich weiß nicht, ob es ein Bug oder was ist, aber nach dem Aktualisieren der Catch-Anweisung, um beide zu fangen, wurde das Problem gelöst.

Hoffe es hilft!