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.