2013-03-05 6 views
7

Sono confuso nell'utilizzo della classe dell'endpoint generato automaticamente. Voglio utilizzare l'endpoint generato per inserire un nuovo oggetto in archivio dati. Ma, un'eccezione sta lanciando.L'eccezione di punto nullo viene generata quando si inserisce un'entità utilizzando il metodo di inserimento del Classendpoint generato automaticamente

fooEndpoint.insertFoo(foo); // throws null pointer exception 

La mia classe di entità è simile con l'esempio dato a questa fonte: https://developers.google.com/appengine/docs/java/datastore/jpa/overview.

Ecco il mio soggetto:

@Entity 
public class Foo { 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Key ID; 

Ecco la traccia dello stack:

java.lang.NullPointerException 
at org.datanucleus.api.jpa.JPAEntityManager.find(JPAEntityManager.java:318) 
at org.datanucleus.api.jpa.JPAEntityManager.find(JPAEntityManager.java:256) 
at com.FooEndpoint.containsFoo(FooEndpoint.java:150) 
at com.FooEndpoint.insertFoo(FooEndpoint.java:96) 

Dall'altro lato, posso inserire un nuovo oggetto quando uso il metodo persistente EntityManager. Perché, questo non verifica esistere o meno sul datastore.

Mi aspetto che, il metodo di inserimento di classEndpoint dovrebbe salvare l'oggetto e assegnare la chiave automatica al campo ID.

Oppure ho bisogno di inizializzare il campo ID.

Qui è il metodo insertFoo della classe dell'endpoint generato automaticamente.

/** 
* This inserts a new entity into App Engine datastore. If the entity already 
* exists in the datastore, an exception is thrown. 
* It uses HTTP POST method. 
* 
* @param foo the entity to be inserted. 
* @return The inserted entity. 
*/ 
public Foo insertFoo(Foo foo) { 
    EntityManager mgr = getEntityManager(); 
    try { 
     if (containsFoo(foo)) { 
      throw new EntityExistsException("Object already exists"); 
     } 
     mgr.persist(foo); 
    } finally { 
     mgr.close(); 
    } 
    return foo; 
} 

Ecco il metodo containsFoo

private boolean containsFoo(Foo foo) { 
    EntityManager mgr = getEntityManager(); 
    boolean contains = true; 
    try { 
     Foo item = mgr.find(Foo.class, foo.getID()); // exception occurs here 
     if (item == null) { 
      contains = false; 
     } 
    } finally { 
     mgr.close(); 
    } 
    return contains; 
} 

foo.getID() è nullo. Perché, è un nuovo oggetto. Mi aspetto che, il motore di app crea una chiave per questo. O ho bisogno di creare esplicitamente una chiave per questo?

Altri campi in classe Foo sono tipi semplici come String e booleani.

Grazie per il vostro tempo.

+1

È possibile fornire l'origine per il metodo 'insertFoo'? Cosa stai passando come "pippo"? –

+0

Mi rendo conto che la vecchia versione del metodo di inserimento del generatore di endpoint cloud è diversa dalla nuova versione. Perché, il metodo insert alla vecchia versione rende persistente l'oggetto senza controllo di esistenza (contiene metodo). Ma i nuovi controllano l'esistenza dell'oggetto. Ma, se la chiave è nullo, viene lanciata un'eccezione. Per favore, questo caso è normale o no? – retto

risposta

8

Ho avuto esattamente lo stesso problema. Presenterò il modo in cui ho lavorato intorno ad esso.

originale auto-generata classe Endpoint codice rilevante:

private boolean containsFoo(Foo foo) { 
    EntityManager mgr = getEntityManager(); 
    boolean contains = true; 
    try { 
     Foo item = mgr.find(Foo.class, foo.getID()); 
     if (item == null) { 
      contains = false; 
     } 
    } finally { 
     mgr.close(); 
    } 
    return contains; 
} 

cambiato relativo codice per includere un controllo nullo per l'oggetto entità che viene passato come argomento.

private boolean containsFoo(Foo foo) { 
    EntityManager mgr = getEntityManager(); 
    boolean contains = true; 
    try { 
     // If no ID was set, the entity doesn't exist yet. 
     if(foo.getID() == null) 
      return false; 
     Foo item = mgr.find(Foo.class, foo.getID()); 
     if (item == null) { 
      contains = false; 
     } 
    } finally { 
     mgr.close(); 
    } 
    return contains; 
} 

In questo modo funzionerà come supposto, anche se sono sicuro che appariranno risposte più esperti e spiegazioni.

+0

Il metodo containsFoo utilizza il metodo find() di Entity Manager, che nel contesto della domanda originale prende un ID nullo e si arresta in modo anomalo, non essendo nemmeno in grado di stabilire se l'archivio dati contiene o meno quell'entità. La mia domanda è: se le nuove entità non hanno un ID, come possono essere verificate per esistenza che richiedono un ID valido? – igordcard

2

Avevo lo stesso esatto problema dopo aver utilizzato il plugin Eclipse per la generazione automatica degli endpoint cloud (selezionando "Google> Genera classe Cloud Endpoint").

seguito il tuo consiglio, ho aggiunto:

se (foo.getID() == null) // sostituite foo con il nome del proprio oggetto return false;

Il problema è stato risolto.

In che modo Google non ha ancora aggiornato il codice generato automaticamente poiché si tratta di un problema ricorrente?

Grazie per la soluzione.