1
votes

I'm trying to add a new root entity with the following code:

    try {
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Key eventKey = datastore.allocateIds("Event", 1).getStart();
        String keyString = KeyFactory.keyToString(eventKey);

        //TransactionOptions options = TransactionOptions.Builder.withXG(true);
        Transaction txn = datastore.beginTransaction();
        Entity eventEntity = new Entity("Event", keyString);

        datastore.put(eventEntity);

        txn.commit();
    } catch (Exception e) {
        log.log(Level.SEVERE, e.getMessage(), e);
        throw new InternalServerErrorException(e);
    }

It's a simple transactional datastore insert that according to the documents suppose to work -

each root entity belongs to a separate entity group, so a single transaction cannot create or operate on more than one root entity unless it is an XG transaction

My 'Event' entity doesnt have any ancestor And i'm only handling it inside the transaction. But for some reason i get the following exception :

java.lang.IllegalArgumentException: cross-group transaction need to be explicitly specified, see TransactionOptions.Builder.withXGfound both Element { type: "Event" id: 4 } and Element { type: "Event" name: "ahBldmVudHNmaW5kZXIyMDEzcgsLEgVFdmVudBgEDA" }

Any idea whats wrong here ?

2

2 Answers

0
votes

Your code just worked for me. I pasted it into the middle of a simple application that was running anyway, ran it twice and it created two "Event" entities and did not throw any exceptions. Your application has a problem elsewhere.

0
votes

Ok, the problem was because i was calling the following method inside the transcation :

private boolean containsEvent(Key eventKey) {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    boolean contains = true;
    try {
        if (eventKey == null) {
            return false;
        }

        Entity eventEntity = datastore.get(eventKey);
        if (eventEntity == null) {
            contains = false;
        }
    } catch (com.google.appengine.api.datastore.EntityNotFoundException e) {
        contains = false;
    }
    return contains;
}

This code only checks if this entity already exists in the datastore.
Appearantly, because the entity wasnt yet commited, this is treated like getting a different root entity and therefore making it a XG operation. Once i moved this method call outside the transaction everything is working fine.