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();
}
});
}
}
});
}
});
}
}
<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