Batch Processing And Transaction Rollback
nathandennis Jun 4, 2009 12:27 AMI am trying to preform batch processing on a large amount of data. Start from a quartz cron job, I'm collecting records from the DB , moving these records to an arraylist, and remotely connecting to a foreign server to processing foreign transaction for each record retrieved. my question is, if something go a miss and the seams managed transaction breaks due to an exception,
how can i keep the entire group of changes from being rolled back? some code....
@Transactional @Name("startupBilling") public class StartupBilling { @Logger private Log log; @In AsyncBillingProcessor asyncBillingProcessor; @Observer("org.jboss.seam.postInitialization") public void observe() { try { log.info("Trying to Start Cron Job"); Calendar cal = Calendar.getInstance (); cal.set (2040, Calendar.MAY, 10); QuartzTriggerHandle handle = asyncBillingProcessor.scheduleBillingQue(new Date(), "0 0 0 * * ?", cal.getTime()); } catch(Exception e) { e.printStackTrace(); log.info("Operation Failed"); } log.info("Job Started"); } }
@Name("asyncBillingProcessor") @AutoCreate public class AsyncBillingProcessor { @Logger Log log; @In EntityManager entityManager; @SuppressWarnings("unchecked") @Asynchronous @Transactional @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public QuartzTriggerHandle scheduleBillingQue(@Expiration Date when, @IntervalCron String cron, @FinalExpiration Date endDate) { ArrayList<Systemsettings> ss = (ArrayList<Systemsettings>) entityManager.createQuery("from Systemsetting where name=:param") .setParameter("param", "recurringbilling") .getSingleResult(); if(ss.size() > 0){ if(ss.get(0).isSw1()){ RecurringBillingLocal rb = (RecurringBillingLocal) Component.getInstance("recurringBillingAction"); Boolean sw = rb.billingProcess(); log.info("billing processed successfully? " + sw); } } return null; } }
@Stateful @Name("recurringBillingAction") @Scope(ScopeType.EVENT) public class RecurringBillingAction implements RecurringBillingLocal { @PersistenceContext private EntityManager entityManager; @Logger private Log log; @In private Renderer renderer; private ArrayList<Userlogin> userlogin; private ArrayList<UserloginInvoiceWrapper> uli = new ArrayList<UserloginInvoiceWrapper>(); private UserloginInvoiceWrapper activeuser; private Userlogin activeadmin; public Boolean billingProcess(){ Calendar today = Calendar.getInstance(); Calendar leap = Calendar.getInstance(); leap.set(today.get(Calendar.YEAR), Calendar.FEBRUARY, 28); try{ if(today.get(Calendar.MONTH)==0){//Calendar.Month starts at 0 = jan log.info("we are in january"); this.userlogin = (ArrayList<Userlogin>) entityManager.createQuery("from Userlogin where year=:lastyear and month=9 and day=:day") .setParameter("lastyear", today.get(Calendar.YEAR) -1) .setParameter("day", today.get(Calendar.DAY_OF_MONTH)) .getResultList(); .....
based on date grab the matching records and preform the billing.
how can i stop a transaction rollback on the entire record set in the event on record fails?
i realize this might require me to change the design slightly.
i've seen annotation such as
@ApplicationException(rollback=false)
that i have a feeling might be helpful, but im not sure. any direction would be greatly appreciated.