Jay
Jay

Reputation: 20136

Correct handling the rollback of a transaction using google app engine

I am not sure if I am understanding the google documentation, I am wondering if someone else can check my understanding.

Is the following code guaranteed to only ever do both of the following:

Below is what I understand is correct:

public void add(String account, Double value, String description, Date date) throws EntityNotFoundException {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    int retries = 3;
    while (true) {
        Transaction txn = datastore.beginTransaction();
        try {

            // Update the bank balance
            Key key = KeyFactory.createKey("Account", account);
            Entity e = datastore.get(key);
            Double balance = (Double) e.getProperty("balance");
            balance += value;
            e.setProperty("balance", value);
            datastore.put(e);

            // Record transaction details
            Entity d = new Entity("Transaction", key);
            d.setProperty("account_key", key);
            d.setProperty("date", date);
            d.setProperty("value", value);
            d.setProperty("description", description);

            txn.commit();
            break;
        } catch (ConcurrentModificationException e) {
            if (retries == 0) throw e;
            retries--;
        } finally {
            if (txn.isActive()) txn.rollback();
        }
    }
    }
}

Upvotes: 3

Views: 286

Answers (2)

Diamond Hands
Diamond Hands

Reputation: 803

Not necessarily a ConcurrentModificationException indicates that a transaction failed. It's an absolute ambiguity in the documentation http://code.google.com/appengine/docs/java/datastore/transactions.html where it says "If your app receives an exception when submitting a transaction, it does not always mean that the transaction failed. You can receive DatastoreTimeoutException, ConcurrentModificationException, or DatastoreFailureException exceptions in cases where transactions have been committed and eventually will be applied successfully. Whenever possible, make your Datastore transactions idempotent so that if you repeat a transaction, the end result will be the same." I've created a separate topic for this issue here Transactions and ConcurrentModificationException documentation ambiguity so if anyone understands how it really should be dealt with, please update there as well.

Upvotes: 0

Nick Johnson
Nick Johnson

Reputation: 101149

That's correct. It's not necessary to include the key of the account in the entity, though - the entity you're creating is a child of the account in question.

Upvotes: 2

Related Questions