`TransCalculator.java`
`01 package trail.transaction; 02 03 import trail.entity.beans.*; 04 import javax.ejb.*; 05 import javax.persistence.*; 06 import javax.annotation.Resource; 07 import java.util.*; 08 09 @Stateless 10 public class TransCalculator implements Calculator { 11 12 @PersistenceContext 13 protected EntityManager em; 14 15 public Collection <TimedRecord> getRecords () { 16 return em.createQuery("from TimedRecord r order by r.id desc").getResultList(); 17 } 18 19 @TransactionAttribute(TransactionAttributeType.REQUIRED) 20 public void updateExchangeRate (double newrate) throws Exception { 21 Collection <TimedRecord> rc = em.createQuery("from TimedRecord r").getResultList(); 22 int size = rc.size(); 23 24 for (Iterator iter = rc.iterator(); iter.hasNext();) { 25 TimedRecord r = (TimedRecord) iter.next(); 26 r.setSaving(r.getSaving() * newrate); 27 r.setResult(r.getResult() * newrate); 28 29 // Emulate a failure 30 31 // Calculate failure probability for each loop 32 // in order for the overall failure probability 33 // to be 50% 34 double prob = Math.pow (0.5, 1./size); 35 if (Math.random() > prob) { 36 // Emulated failure causes rollback 37 throw new TransException (); 38 39 // Or throw a RuntimeException to trigger rollback 40 } 41 } 42 } 43 44 @TransactionAttribute(TransactionAttributeType.REQUIRED) 45 public void updateExchangeRate2 (double newrate) throws Exception { 46 Collection <TimedRecord> rc = em.createQuery("from TimedRecord r").getResultList(); 47 for (Iterator iter = rc.iterator(); iter.hasNext();) { 48 TimedRecord r = (TimedRecord) iter.next(); 49 r.setSaving(r.getSaving() * newrate); 50 r.setResult(r.getResult() * newrate); 51 52 // Emulate a database failure 53 int status = (int) (Math.random () * 4.); 54 System.err.println("status is " + status); 55 if (status == 3) { 56 throw new RuntimeException ("Emulated database failure"); 57 } 58 // Synchronize the persistence context to the DB 59 // All flushed updates will be removed from the DB 60 // if the transaction is rolled back 61 em.flush(); 62 } 63 // em.flush(); 64 } 65 }`