Question

Infinispan documentation says a lot of stuff about its locking scheme, optimistic and pessimistic, but fails to detail how to use the transactions. Probably it is assumed to be know, because it uses Java's default API, but if it is so, I also failed to find about JTA usage patterns.

I assume, when using optimistic transactions, that it will be either committed or rolled back, depending on the concurrent access to the data, and if it is rolled back, I will be able to replay the transaction, hoping that now it will get done before other concurrent access and will succeed. I have the begin(), commit() and rollback() methods on the TransactionManager, and badly documented exceptions that I am not sure when they will be thrown. With this information, I had made up this code:

public void transactionSum(Key key, Long delta) {
    boolean redo;
    do{
        redo = false;
        try {
            tm.begin();
            try {
                Long value = cache.get(key);
                // Some processing:
                value += delta;
                cache.put(key, value);
                tm.commit();
            } catch(CacheException e) {
                tm.rollback();
                throw new RollbackException();
            }
        } catch (RollbackException e) {
            redo = true;
            logger.debug("Cache transaction collision, replaying it.");
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    } while(redo);
}

Is this code correct? It seems overly complicated for performing an operation that is supposedly common, thus I suspect I've done something wrong... Will some CacheException be thrown if cache.put() fails? If so, should I explicitly call tm.rollback()? What if I called tm.commit() inside a finally clause? When would it throw a RollbackException?

More importantly, is there some idiom/default way to perform transaction replays?

Was it helpful?

Solution

The correct pattern is:

Transaction tx = tm.begin();
try
{
// DO SOMETHING
}
catch (Exception e)
{
   tx.setRollbackOnly(); // Force a rollback for this error
   throw e;
}
finally
{
   if (tx.getStatus() == Status.STATUS_ACTIVE)
      tx.commit();
   else
      tx.rollback();
}

Without a functional language, the easiest way to consume this is via callables or similar patterns, i.e. https://github.com/galderz/infinispan/blob/master/core/src/test/java/org/infinispan/test/TestingUtil.java#L1307

Update: there's no functionality to retry transactions in Infinispan

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top