GAE (Google App Engine) allows you to use an ORM library to map your noSQL data. In my test I’ve used JPA v.1.
To expose data I’ve implemented a REST API using Jersey. In this short article I don’t want to explain how to implement the complete application but how to solve the following Error
java.lang.IllegalArgumentException: app s~<yourappname> cannot access app <yourappname>'s data at com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:36) at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException(DatastoreApiHelper.java:76) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:106) at com.google.appengine.api.datastore.FutureHelper$CumulativeAggregateFuture.get(FutureHelper.java:145) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:90) at com.google.appengine.api.datastore.FutureHelper.getInternal(FutureHelper.java:72) at com.google.appengine.api.datastore.FutureHelper.quietGet(FutureHelper.java:33) at com.google.appengine.api.datastore.DatastoreServiceImpl$2.runInternal(DatastoreServiceImpl.java:113) at com.google.appengine.api.datastore.DatastoreServiceImpl$2.runInternal(DatastoreServiceImpl.java:110) at com.google.appengine.api.datastore.TransactionRunner.runInTransaction(TransactionRunner.java:31) at com.google.appengine.api.datastore.DatastoreServiceImpl.put(DatastoreServiceImpl.java:110) <continued in next message>
This Error occurs only when you use the application on GAE and not when you debug locally.
In my experience the error is related to the Entity Key.
If you try to create a new Entity forcing the Key you have this error. Why you may incur in this? Because you are copy another Entity! So remember to clear the Entity Key in the copy constructor.
Another way to face this problem is using REST: if you are creating a new Entity and in the JSON posted you force the Key GAE log this error.
This is the example. The Entity
public interface BasicEntity<T> {
public void createVersion();
public void updateVersion(T old);
public boolean isRemoved();
public String getUUID();
}
@Entity
public class Utente implements Serializable, BasicEntity<Utente> {
/**
*
*/
private static final long serialVersionUID = -6565127229887272677L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
private Key key;
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
// server
@Transient
@JsonProperty("uuid")
private String UUID;
public String getUUID() {
UUID = KeyFactory.keyToString(key);
return UUID;
}
public void setUUID(String UUID) {
this.UUID = UUID;
key = KeyFactory.stringToKey(UUID);
}
// vecchio id
private String id;
// id generato dal client
private String clientUUID;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClientUUID() {
return clientUUID;
}
public void setClientUUID(String clientUUID) {
this.clientUUID = clientUUID;
}
@Basic
private Long versione;
// fields
@Basic
private String email;
@Basic
@JsonIgnore
private String encryptedPwd;
@Basic
private String nome;
@Basic
private String azienda;
@Basic
private Boolean abilitato;
public String getEmail() {
return email;
}
public void setEmail(String eMail) {
this.email = eMail;
}
public String getEncryptedPwd() {
return encryptedPwd;
}
public void setEncryptedPwd(String encryptedPwd) {
this.encryptedPwd = encryptedPwd;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getAzienda() {
return azienda;
}
public void setAzienda(String azienda) {
this.azienda = azienda;
}
public Boolean getAbilitato() {
return abilitato;
}
public void setAbilitato(Boolean abilitato) {
this.abilitato = abilitato;
}
@Override
public void updateVersion(Utente old) {
// TODO Auto-generated method stub
}
@Override
public void createVersion() {
// TODO Auto-generated method stub
}
public Long getVersione() {
return versione;
}
public void setVersione(Long versione) {
this.versione = versione;
}
private boolean removed;
@Override
public boolean isRemoved() {
return removed;
}
public void setRemoved(boolean removed) {
this.removed = removed;
}
}
DAO
public abstract class BasicDAO<T extends BasicEntity<T>> {
private EntityManager em;
protected abstract String getClassName();
protected abstract Class<?> getClassType();
public BasicDAO() {
startTransaction();
}
public void startTransaction() {
setEm(EMF.get().createEntityManager());
}
public void endTransaction() {
getEm().close();
}
public EntityManager getEm() {
return em;
}
public void setEm(EntityManager em) {
this.em = em;
}
@SuppressWarnings("unchecked")
protected T get(String id) {
return (T) getEm().find(getClassType(), id);
}
protected T insert(T myObject) {
myObject.createVersion();
getEm().persist(myObject);
getEm().refresh(myObject);
return myObject;
}
protected T update(T myObject, String uuid) {
if (myObject.getUUID() != null && myObject.getUUID().equalsIgnoreCase(uuid)) {
T old = get(uuid);
if (old != null) {
myObject.updateVersion(old);
getEm().persist(myObject);
getEm().refresh(myObject);
}
return myObject;
}
return null;
}
protected boolean delete(String id) {
boolean ok = false;
Object myObject = get(id);
if (myObject != null) {
getEm().remove(myObject);
ok = true;
}
return ok;
}
protected abstract T reattach(T myObject);
@SuppressWarnings("unchecked")
protected List<T> gets() {
return (List<T>) getEm().createQuery("Select from " + getClassName())
.getResultList();
}
}
public class UtenteDAO extends BasicDAO<Utente> {
public Utente getUtente(String id) {
return get(id);
}
public void insertUtente(Utente utente) {
insert(utente);
}
public void updateUtente(Utente utente, String id) {
updateUtente(utente, id);
}
public List<Utente> getUtenti() {
return gets();
}
@Override
protected String getClassName() {
return "Utente";
}
@Override
protected Class<?> getClassType() {
return Utente.class;
}
@Override
protected Utente reattach(Utente myObject) {
// TODO Auto-generated method stub
return null;
}
}
Jersey REST mapping
@Produces(MediaType.APPLICATION_JSON)
@Path("/utenti")
public class UtenteResource {
@GET
@Path("/")
public List<Utente> getUtentu() {
UtenteDAO dao = new UtenteDAO();
return dao.getUtenti();
}
@GET
@Path("/{id}")
public Utente getPraticaById(@PathParam("id") String id) {
UtenteDAO dao = new UtenteDAO();
return dao.getUtente(id);
}
@POST
@Path("/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public void updateUtente(@Context HttpServletRequest Req, Utente utente, @PathParam("id") String id) {
UtenteDAO dao = new UtenteDAO();
dao.updateUtente(utente, id);
}
@POST
@Path("/new")
@Consumes(MediaType.APPLICATION_JSON)
public void insertUtente(@Context HttpServletRequest Req, Utente utente) {
UtenteDAO dao = new UtenteDAO();
dao.insertUtente(utente);
}
}
The JSON posted that give you the error
curl -H “Content-Type: application/json” -X POST –data @jsontest/new_user.json http://localhost:8888/rest/utenti/new
{
"uuid": "agxpbGVnYWxlY2xvdWRyGwsSB1ByYXRpY2EYlAIMCxIGVXRlbnRlGJYCDA",
"id": null,
"clientUUID": null,
"versione": null,
"email": "giulio.roggero@gmail.com",
"encryptedPwd": "adskasdhkasjhjakshd832329y",
"nome": "Giulio Roggero",
"azienda": "Isola Software",
"abilitato": true
}
remove uuid and you can create a new user
{
"id": null,
"clientUUID": null,
"versione": null,
"email": "giulio.roggero@gmail.com",
"encryptedPwd": "adskasdhkasjhjakshd832329y",
"nome": "Giulio Roggero",
"azienda": "Isola Software",
"abilitato": true
}

