Thursday, 27 June 2013

Cron in Spring


STEP [1] create a synchronized job processor


import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.data.jpa.domain.AbstractPersistable;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionOperations;

public abstract class JobProcessorSynchronized<T extends AbstractPersistable<Long>> {

private final TransactionOperations transactionOperations;

private final ExecutorService executorService = Executors.newSingleThreadExecutor();

private Long lastJobId;

public JobProcessorSynchronized(TransactionOperations transactionOperations) {
this.transactionOperations = transactionOperations;

}

public abstract List<T> getJobsTobeExcecuted(Long lastJobId);

protected abstract void processJob(T job);

public void process() {
this.lastJobId = new Long(0);
processInBackground();
}

public void processInBackground() {
executorService.execute(new Runnable() {

@Override
public void run() {

transactionOperations.execute(new TransactionCallbackWithoutResult() {

@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
List<T> jobs = getJobsTobeExcecuted(lastJobId);
for (T job : jobs) {
processJob(job);
lastJobId = job.getId();
}

status.flush();

if (jobs.size() > 0) {
executorService.execute(new Runnable() {

@Override
public void run() {
processInBackground();

}
});
}

}
});

}
});
}
}

@Inject transactionOperations via spring-context.xml

<constructor-arg>
<bean class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager" />
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW" />
</bean>
</constructor-arg>



STEP [2] Define class and method for job
public class BloodoverflowJob extends JobProcessorSynchronized<Reminder>{


      @Override
public List<Reminder> getJobsTobeExcecuted(Long lastJobId)   {
return list; //with @Lock(LockModeType.PESSIMISTIC_WRITE)
}

      @Override
      public void processJob(){
         //logic here
      }
}


STEP [3] Add the following content to spring context

<task:annotation-driven executor="asyncExecutor" />
<task:executor id="asyncExecutor" pool-size="5" />
<task:scheduler id="bloodoverflowRemindSchedular" pool-size="1" />
<task:scheduled-tasks scheduler="bloodoverflowRemindScheduler">

<task:scheduled ref="bloodoverflowJob" method="process" cron="${bloodoverflowJob.cron}" />
</task:scheduled-tasks>


process is a method of bean bloodoverflowJob.

STEP [4] Define job cron expression in properties file
Fire at 12:00 PM (noon) every day
bloodoverflowJob.cron = 0 0 12 * * ?

OR

# Fire at every 05 minutes
bloodoverflowJob.cron = 0 0 0/05 * * *


Reference
http://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm

Cluster job synchronization with Spring AOP and memcached, http://blog.oio.de/2013/07/03/cluster-job-synchronization-with-spring-aop-and-memcached/

Java ExecutorService, http://www.itcuties.com/java/executorservice/

No comments:

Post a Comment