![JAR search and dependency download from the Maven repository](/logo.png)
org.jbpm.job.executor.JobExecutorThread Maven / Gradle / Ivy
package org.jbpm.job.executor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.JobSession;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.job.Job;
import org.jbpm.persistence.db.DbPersistenceService;
import org.jbpm.persistence.db.StaleObjectLogConfigurer;
public class JobExecutorThread extends Thread implements Deactivable {
private final JobExecutor jobExecutor;
private volatile boolean active = true;
private Random random = new Random() ;
public JobExecutorThread(String name, JobExecutor jobExecutor) {
super(jobExecutor.getThreadGroup(), name);
this.jobExecutor = jobExecutor;
}
/**
* @deprecated use {@link #JobExecutorThread(String, JobExecutor)} instead
*/
public JobExecutorThread(String name, JobExecutor jobExecutor,
JbpmConfiguration jbpmConfiguration, int idleInterval, int maxIdleInterval,
long maxLockTime, int maxHistory) {
super(jobExecutor.getThreadGroup(), name);
this.jobExecutor = jobExecutor;
}
public void run() {
while (active) {
// take on next job
Job job = jobExecutor.getJob();
// if an exception occurs, acquireJob() returns null
if (job != null) {
try {
executeJob(job);
}
catch (Exception e) {
// save exception stack trace
// if another exception occurs, it is not rethrown
saveJobException(job, e);
}
catch (Error e) {
// unlock job so it can be dispatched again
// if another exception occurs, it is not rethrown
unlockJob(job);
throw e;
}
}
}
log.info(getName() + " leaves cyberspace");
}
/** @deprecated responsibility moved to DispatcherThread **/
protected Collection acquireJobs() {
Collection jobs = Collections.EMPTY_LIST;
boolean debug = log.isDebugEnabled();
JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
try {
// search for available job
String lockOwner = getName();
JobSession jobSession = jbpmContext.getJobSession();
Job firstJob = jobSession.getFirstAcquirableJob(lockOwner);
// is there a job?
if (firstJob != null) {
// is job exclusive?
if (firstJob.isExclusive()) {
// find other exclusive jobs
ProcessInstance processInstance = firstJob.getProcessInstance();
List exclusiveJobs = jobSession.findExclusiveJobs(lockOwner, processInstance);
if (debug) log.debug("acquiring " + exclusiveJobs + " for " + processInstance);
Date lockTime = new Date();
for (Iterator i = exclusiveJobs.iterator(); i.hasNext();) {
Job exclusiveJob = (Job) i.next();
exclusiveJob.setLockOwner(lockOwner);
exclusiveJob.setLockTime(lockTime);
}
// deliver result
if (debug) log.debug("acquired " + exclusiveJobs);
jobs = exclusiveJobs;
}
else {
if (debug) log.debug("acquiring " + firstJob);
firstJob.setLockOwner(lockOwner);
firstJob.setLockTime(new Date());
// deliver result
if (debug) log.debug("acquired " + firstJob);
jobs = Collections.singletonList(firstJob);
}
}
else if (debug) log.debug("no acquirable job found");
}
catch (RuntimeException e) {
jbpmContext.setRollbackOnly();
if (debug) log.debug("failed to acquire jobs", e);
}
catch (Error e) {
jbpmContext.setRollbackOnly();
throw e;
}
finally {
try {
jbpmContext.close();
}
catch (RuntimeException e) {
jobs = Collections.EMPTY_LIST;
if (debug) log.debug("failed to acquire jobs", e);
}
}
return jobs;
}
protected void executeJob(Job job) throws Exception {
JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
try {
// reattach job to persistence context
JobSession jobSession = jbpmContext.getJobSession();
jobSession.reattachJob(job);
// register process instance for automatic save
// https://jira.jboss.org/browse/JBPM-1015
ProcessInstance processInstance = job.getProcessInstance();
jbpmContext.addAutoSaveProcessInstance(processInstance);
// if job is exclusive, lock process instance
if (job.isExclusive()) {
jbpmContext.getGraphSession().lockProcessInstance(processInstance);
}
if (log.isDebugEnabled()) log.debug("executing " + job);
if (job.execute(jbpmContext)) jobSession.deleteJob(job);
}
catch (Exception e) {
jbpmContext.setRollbackOnly();
throw e;
}
catch (Error e) {
jbpmContext.setRollbackOnly();
throw e;
}
finally {
jbpmContext.close();
}
}
private void saveJobException(Job job, Exception exception) {
// if this is a locking exception, keep it quiet
if (DbPersistenceService.isLockingException(exception)) {
StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
.error("failed to execute " + job, exception);
}
else {
log.error("failed to execute " + job, exception);
}
JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
try {
// do not reattach existing job as it contains undesired updates
jbpmContext.getSession().refresh(job);
// print and save exception
StringWriter out = new StringWriter();
exception.printStackTrace(new PrintWriter(out));
job.setException(out.toString());
// unlock job so it can be dispatched again
job.setLockOwner(null);
job.setLockTime(null);
int waitPeriod = jobExecutor.getRetryInterval() / 2;
waitPeriod += random.nextInt(waitPeriod) ;
job.setDueDate(new Date(System.currentTimeMillis() + waitPeriod)) ;
}
catch (RuntimeException e) {
jbpmContext.setRollbackOnly();
log.warn("failed to save exception for " + job, e);
}
catch (Error e) {
jbpmContext.setRollbackOnly();
throw e;
}
finally {
try {
jbpmContext.close();
}
catch (RuntimeException e) {
log.warn("failed to save exception for " + job, e);
}
}
// notify job executor
synchronized (jobExecutor) {
jobExecutor.notify();
}
}
private void unlockJob(Job job) {
JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
try {
// do not reattach existing job as it contains undesired updates
jbpmContext.getSession().refresh(job);
// unlock job
job.setLockOwner(null);
job.setLockTime(null);
if (job.getException() != null)
{
job.setRetries(job.getRetries()+1) ;
}
}
catch (RuntimeException e) {
jbpmContext.setRollbackOnly();
log.warn("failed to unlock " + job, e);
}
catch (Error e) {
jbpmContext.setRollbackOnly();
// do not rethrow as this method is already called in response to an Error
log.warn("failed to unlock " + job, e);
}
finally {
try {
jbpmContext.close();
}
catch (RuntimeException e) {
log.warn("failed to unlock " + job, e);
}
}
// notify job executor
synchronized (jobExecutor) {
jobExecutor.notify();
}
}
/** @deprecated responsibility moved to DispatcherThread */
protected long getWaitPeriod(int currentIdleInterval) {
Date nextDueDate = getNextDueDate();
if (nextDueDate != null) {
long waitPeriod = nextDueDate.getTime() - System.currentTimeMillis();
if (waitPeriod < currentIdleInterval) return waitPeriod;
}
return currentIdleInterval;
}
/** @deprecated responsibility moved to DispatcherThread */
protected Date getNextDueDate() {
Date nextDueDate = null;
JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
try {
String lockOwner = getName();
Job job = jbpmContext.getJobSession()
.getFirstDueJob(lockOwner, jobExecutor.getMonitoredJobIds());
if (job != null) {
jobExecutor.addMonitoredJobId(lockOwner, job.getId());
nextDueDate = job.getDueDate();
}
else if (log.isDebugEnabled()) log.debug("no due job found");
}
catch (RuntimeException e) {
jbpmContext.setRollbackOnly();
if (log.isDebugEnabled()) log.debug("failed to determine next due date", e);
}
catch (Error e) {
jbpmContext.setRollbackOnly();
throw e;
}
finally {
try {
jbpmContext.close();
}
catch (RuntimeException e) {
nextDueDate = null;
if (log.isDebugEnabled()) log.debug("failed to determine next due date", e);
}
}
return nextDueDate;
}
/**
* @deprecated As of jBPM 3.2.3, replaced by {@link #deactivate()}
*/
public void setActive(boolean isActive) {
if (isActive == false) deactivate();
}
public void deactivate() {
if (active) {
active = false;
interrupt();
}
}
private static final Log log = LogFactory.getLog(JobExecutorThread.class);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy