Transaction handling in relation to ConcurrentModificationException

34 views
Skip to first unread message

Louise Elmose Hedegaard

unread,
Feb 21, 2017, 8:33:04 AM2/21/17
to Google App Engine
Hi,

I have a scenario where I try to delete a number of entities from the datastore.
The operation fails with a ConcurrentModificationException, and I expect my code below to handle this scenario and rollback.
The exception is thrown in transactionsHandler.commit(), more specifically on transaction.commit(); - this causes the flow to go to the finally block, but it turns out the transaction is no longer active, and thus the transaction is not rolled back, causing an inconsistent datastore.
How should I handle the scenario instead?

Thanks,
-Louise

Code:

Transaction transaction = transactionHandler.begin();

try {
execute(transaction);//Delete entities from datastore
logger.info("Initiating commit of transaction");
transactionHandler.commit();
} finally {
transactionHandler.tryRollback();
}

public class TransactionHandler{
private Logger logger = Logger.getLogger(this.getClass().getName());
private Transaction transaction;

public Transaction begin(){
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
TransactionOptions options = TransactionOptions.Builder.withXG(true);
transaction = datastore.beginTransaction(options);
return transaction;
}

public void commit(){
if (transaction.isActive()){
transaction.commit();
logger.info("Transaction comittet");
}else{
logger.warning("Transaction was not active - transaction was not comittet");
}
}

public void tryRollback(){
if (transaction.isActive()){
transaction.rollback();
logger.info("Transaction rolled back as transaction was still active");
}else{
logger.info("Transaction was not active - transaction was not rolledback");
}
}
}

George (Cloud Platform Support)

unread,
Feb 22, 2017, 12:03:25 PM2/22/17
to Google App Engine

Hello Louise,


Your code starts with a “try { “ but doesn’t throw any exception. You might be interested in the DatastoreTimeoutException as exemplified in the “Handling Datastore Errors” online document. A sample statement looks like: catch (ConcurrentModificationException e).


To properly roll back your transaction, you may consider following the examples provided in the “Transactions” document.


Because the Cloud Datastore API does not retry transactions, you may consider adding logic so that your app provides the same functionality, in your case to delete a number of entities, analogous to the   appengine/datastore/src/test/java/com/example/appengine/TransactionsTest.java sample code from this document.

Reply all
Reply to author
Forward
0 new messages