Hi

I'm not sure if it's possible what I'm trying to do. But for our 
application I also have to gather data from a 3rd-party API and I would 
like to persist the to the datastore for caching reasons.

To implement the solution I'm using Eclipse with the App Engine plugin and 
I have created a simple entity like this:

import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;


@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Bird {
 @PrimaryKey
 @Persistent
 long id; 
 @Persistent
 String name;
 @Persistent
 String germanName;
 @Persistent
 String englishName;
 @Persistent 
 String frenchName;
 @Persistent
 String italianName;
 
 public long getId() {
 return id;
 }
 public void setId(long id) {
 this.id = id;
 }
 public String getGermanName() {
 return germanName;
 }
 public void setGermanName(String germanName) {
 this.germanName = germanName;
 }
 public String getEnglishName() {
 return englishName;
 }
 public void setEnglishName(String englishName) {
 this.englishName = englishName;
 }
 public String getFrenchName() {
 return frenchName;
 }
 public void setFrenchName(String frenchName) {
 this.frenchName = frenchName;
 }
 public String getItalianName() {
 return italianName;
 }
 public void setItalianName(String italianName) {
 this.italianName = italianName;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 } 
}


After that I created an Endpoint with the Eclipse plugin and modified 
listBird slightly (Orange part in the following code), Of course it makes 
no sense at all to do what I'm doing here, but I just want to give you a 
clean example what's my problem. Usually I would call a third party API to 
gather some data to persist there.

package ch.hslu.testproject;

import ch.hslu.testproject.PMF;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.CollectionResponse;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.datanucleus.query.JDOCursorHelper;

import java.util.HashMap;
import java.util.List;

import javax.annotation.Nullable;
import javax.inject.Named;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

@Api(name = "birdendpoint", namespace = @ApiNamespace(ownerDomain = 
"hslu.ch", ownerName = "hslu.ch", packagePath = "testproject") )
public class BirdEndpoint {

/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* @return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
@SuppressWarnings({ "unchecked", "unused" })
@ApiMethod(name = "listBird")
public CollectionResponse<Bird> listBird(@Nullable @Named("cursor") String 
cursorString,
@Nullable @Named("limit") Integer limit) {

PersistenceManager mgr = null;
Cursor cursor = null;
List<Bird> execute = null;

try {
mgr = getPersistenceManager();
Query query = mgr.newQuery(Bird.class);
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
HashMap<String, Object> extensionMap = new HashMap<String, Object>();
extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
query.setExtensions(extensionMap);
}

if (limit != null) {
query.setRange(0, limit);
}

execute = (List<Bird>) query.execute();
cursor = JDOCursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();

// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (Bird obj : execute)
;
// CUSTOM
if(execute.isEmpty()) {
Bird testBird = new Bird() {{
englishName = "Test";
germanName = "Test";
frenchName = "Test";
italianName = "Test";
}};
mgr.makePersistent(testBird);
}
} finally {
mgr.close();
}

return CollectionResponse.<Bird> 
builder().setItems(execute).setNextPageToken(cursorString).build();
}

/**
* This method gets the entity having primary key id. It uses HTTP GET 
method.
*
* @param id the primary key of the java bean.
* @return The entity with primary key id.
*/
@ApiMethod(name = "getBird")
public Bird getBird(@Named("id") Long id) {
PersistenceManager mgr = getPersistenceManager();
Bird bird = null;
try {
bird = mgr.getObjectById(Bird.class, id);
} finally {
mgr.close();
}
return bird;
}

/**
* 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 bird the entity to be inserted.
* @return The inserted entity.
*/
@ApiMethod(name = "insertBird")
public Bird insertBird(Bird bird) {
PersistenceManager mgr = getPersistenceManager();
try {
if (containsBird(bird)) {
throw new EntityExistsException("Object already exists");
}
mgr.makePersistent(bird);
} finally {
mgr.close();
}
return bird;
}

/**
* This method is used for updating an existing entity. If the entity does 
not
* exist in the datastore, an exception is thrown.
* It uses HTTP PUT method.
*
* @param bird the entity to be updated.
* @return The updated entity.
*/
@ApiMethod(name = "updateBird")
public Bird updateBird(Bird bird) {
PersistenceManager mgr = getPersistenceManager();
try {
if (!containsBird(bird)) {
throw new EntityNotFoundException("Object does not exist");
}
mgr.makePersistent(bird);
} finally {
mgr.close();
}
return bird;
}

/**
* This method removes the entity with primary key id.
* It uses HTTP DELETE method.
*
* @param id the primary key of the entity to be deleted.
*/
@ApiMethod(name = "removeBird")
public void removeBird(@Named("id") Long id) {
PersistenceManager mgr = getPersistenceManager();
try {
Bird bird = mgr.getObjectById(Bird.class, id);
mgr.deletePersistent(bird);
} finally {
mgr.close();
}
}

private boolean containsBird(Bird bird) {
PersistenceManager mgr = getPersistenceManager();
boolean contains = true;
try {
mgr.getObjectById(Bird.class, bird.getId());
} catch (javax.jdo.JDOObjectNotFoundException ex) {
contains = false;
} finally {
mgr.close();
}
return contains;
}

private static PersistenceManager getPersistenceManager() {
return PMF.get().getPersistenceManager();
}

}

If I call my API now, I get the following response:

{
  "error" : {
    "message" : 
"org.datanucleus.api.jdo.exceptions.NoPersistenceInformationException: The 
class \"ch.hslu.testproject.BirdEndpoint$1\" is required to be persistable yet 
no Meta-Data/Annotations can be found for this class. Please check that the 
Meta-Data/annotations is defined in a valid file 
location.\nNestedThrowables:\norg.datanucleus.exceptions.NoPersistenceInformationException:
 The class \"ch.hslu.testproject.BirdEndpoint$1\" is required to be persistable 
yet no Meta-Data/Annotations can be found for this class. Please check that the 
Meta-Data/annotations is defined in a valid file location.",
    "code" : 503,
    "errors" : [ {
      "domain" : "global",
      "reason" : "backendError",
      "message" : 
"org.datanucleus.api.jdo.exceptions.NoPersistenceInformationException: The 
class \"ch.hslu.testproject.BirdEndpoint$1\" is required to be persistable yet 
no Meta-Data/Annotations can be found for this class. Please check that the 
Meta-Data/annotations is defined in a valid file 
location.\nNestedThrowables:\norg.datanucleus.exceptions.NoPersistenceInformationException:
 The class \"ch.hslu.testproject.BirdEndpoint$1\" is required to be persistable 
yet no Meta-Data/Annotations can be found for this class. Please check that the 
Meta-Data/annotations is defined in a valid file location."
    } ]
  }
}


Some people (stackoverflow...) with the same issue have started modifing 
the persistence.xml to get rid of the exception, but I haven't had any 
success doing so. My persistence.xml is still untouched:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence";
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"; 
version="1.0">

    <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
        <properties>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" 
value="true"/>
            <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
    </persistence-unit>
</persistence>


Why am I not allowed to persist the testBird-Object?

Kind regards,
Adrian



-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/google-appengine.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/google-appengine/e5e62fff-86d5-4d1a-af3a-5b0ca1ecb34e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to