package net.oxbeef.transaction;
import java.util.Collection;
import java.util.Iterator;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
@Remote(DriverRemote.class)
public class Driver implements DriverRemote {
@PersistenceContext
protected EntityManager em;
// MAIN ENTRY POINT
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void growLegs() throws Exception {
Collection c = em.createQuery("from Tiger t order by t.numLegs desc")
.getResultList();
Tiger t;
int size = c.size();
for (Iterator i = c.iterator(); i.hasNext();) {
t = (Tiger) i.next();
t.setNumLegs(t.getNumLegs() + 1);
// 50% chance of fail overall
double prob = Math.pow(0.5, 1. / size);
if (Math.random() > prob) {
// Emulated failure causes rollback
// throw new RollingException();
try {
forbidden(t);
} catch( Exception e ) {
throw new RollingException();
}
}
// Synchronize the persistence context to the DB
// All flushed updates will be removed from the DB
// if the transaction is rolled back
em.flush();
}
}
// execution has 50% chance of reaching here. It does get here, but doesn't fail.
@TransactionAttribute(TransactionAttributeType.NEVER)
protected void forbidden(Tiger t) {
System.out.println("trying to do something here");
t.setNumLegs(0);
em.flush();
// why didn't it fail with an EJBException??
}
// just return a list of what's in the db
public int[] getValues() {
int[] list;
try {
Collection c = em.createQuery(
"from Tiger t order by t.numLegs desc").getResultList();
list = new int[c.size()];
int count = 0;
for (Iterator i = c.iterator(); i.hasNext();) {
list[count++] = ((Tiger) i.next()).getNumLegs();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return list;
}
}