2013-02-20 9 views
8

sto usando Goole App Engine per costruire il mio API REST, ho già segnato la mia classe come PersistenceCapable e anche mi sono definito il mio @PrimaryKey e anche contrassegnato come @Persistent (valueStrategy = IdGeneratorStrategy.IDENTITY), inoltre ho già creato EndPoint. ma quando scrivo nella finestra del terminale un comando di arricciatura per inserire una nuova entità o registro non funziona. questo è il codice:Generazione automatica Id IdGeneratorStrategy

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

questo è il comando riccio e la risposta dal mio server locale. quando provo ad inserire una nuova entità

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

e questa è la risposta dal server locale.

"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." 

ho pensato che id è stato generato automaticamente un inserito. ma non sta succedendo qui. A differenza di inserire un id insieme


  1. sono la mia classe sbagliata?
  2. sono la mia richiesta POST/json Ok?

Grazie in anticipo.

+0

e il registro dice cosa? (anche io non posso leggere quei geroglifici che hai postato sopra, non vedo nemmeno il codice di persistenza Java, come pm.makePersistent). – DataNucleus

+0

Potresti aver incollato direttamente i frammenti di codice. Le immagini sono un po 'piccole e difficili da capire. –

+0

Ho già cambiato le immagini per codice snippato ... scusa per le immagini cattive ... – AlexSanchez

risposta

8

Penso di aver trovato la soluzione. Sembra che ogni endpoint generato dal framework Google App Engine (GAE) abbia un metodo semplice che verifica ogni volta che qualcuno sta tentando di inserire o aggiornare e un'istanza persistente, quindi il fatto è stato ogni volta che ho provato a inserire un nuovo studente con ricciolo/jSON senza specificare de nuovo ID per l'istanza è visualizzato un messaggio di errore come questo:

"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. 

così ho risolvere il problema modificando mia classe endpoint controllando se il nuovo oggetto (inviato da comando ricciolo e formato json avvolto) ha un valore id non nullo prima ancora di controllare se l'oggetto è stato memorizzato prima con questo codice:

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

Finora non ho visto alcuna documentazione che possa chiarire questo aspetto per me. Inoltre, aggiungo che passo molto tempo a leggere la documentazione su GAE prima di cercare di capire cosa sta succedendo.


Tutto ciò che mi ha fatto pensare che forse solo forse la documentazione GAE non è aggiornata o probabilmente Io ho mai cercare abbastanza, quindi se qualcuno conosce. per favore fammelo sapere e cresci la conoscenza comune. grazie @DataNucleus.

NOTA: "Questo fork che ho realizzato non dovrebbe essere considerato come risposta corretta, potrebbe portare a comportamenti imprevisti della tua app."

+1

+1 Tu salvato la mia giornata! Questo può essere considerato un bug di GPE che genera il codice indesiderato per Google Cloud Endpoint. –

+2

ciao @ToyHunter, ho fatto qualche ricerca e ho trovato una soluzione migliore. ora sto usando un oggetto Iterator statico che contiene un intervallo di chiavi. quindi ogni volta che POST una nuova entità ottengo la nuova chiave per il nuovo oggetto. ho scritto un metodo statico privato all'interno della classe Endpoint che inizializza l'iteratore, quindi quando POST un nuovo oggetto l'iteratore ottiene una nuova chiave e io la assegno al nuovo oggetto e lo mantengo.qui alcuni [riferimento] (https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyRange) – AlexSanchez

+1

+1 Il tuo approccio è decisamente utile dal punto di vista che si potrebbe desiderare di preservare gli ID attraverso la migrazione dei dati. Mi chiedo solo perché non tutti questi problemi sono già stati curati da App Engine. –

0

Come osservato nella risposta di AlexSanchez, il codice di endpoint generato prevede che la chiave primaria sia già impostata sull'inserimento di nuove identità.

Mentre alcuni possono vedere questo come un bug, altri possono vedere come una funzionalità, perché richiede al client di generare la chiave in qualche modo (ad esempio creando un uuid casuale quando il tipo di chiave è String). In questo modo, il cliente può creare un grafico completo delle entità anche offline e caricarle sul server una volta online.

(ritengo quadro Spine è un esempio di questa idea:. http://spinejs.com/)

1

Il problema sta nel metodo del punto finale che è stato generato automaticamente contiene. L'eccezione generata è javax.jdo.JDOFatalInternalException quando id è nullo e il metodo intercetta l'eccezione javax.jdo.JDOObjectNotFoundException.

L'eccezione non viene mai rilevata e viene visualizzato l'errore. Non lo faccio se si tratta di un bug o di cosa, ma dopo aver aggiornato la dichiarazione di cattura per catturare entrambi, il problema è stato risolto.

Spero che aiuti!