Merged BRANCHES/V3.2 to HEAD:

17409: ETHREEOH-1630 Webscript Kind=org.alfresco.repository.content.stream returns information about the Thumbnail webscript
   17444: Update svn:mergeinfo
   17940: Updated JBPM log level (GraphElement) to hide errors which should be handled by Alfresco retrying txn handler
   17989: AVM - unreported NPE in OrphanRepear (clustered)
   17997: WCM clustering - ensure Alfresco/JBPM job executor handles retries (from Alfresco retrying txn handler)


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19197 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-03-10 17:16:34 +00:00
parent 1b8a6858c0
commit 07a68c5fa6
2 changed files with 134 additions and 36 deletions

View File

@@ -271,6 +271,12 @@ public class OrphanReaper
return null; return null;
} }
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(fPurgeQueue.removeFirst()); AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(fPurgeQueue.removeFirst());
if (node == null)
{
// eg. cluster, multiple reapers
continue;
}
// Save away the ancestor and merged from fields from this node. // Save away the ancestor and merged from fields from this node.
HistoryLink hlink = AVMDAOs.Instance().fHistoryLinkDAO.getByDescendent(node); HistoryLink hlink = AVMDAOs.Instance().fHistoryLinkDAO.getByDescendent(node);
AVMNode ancestor = null; AVMNode ancestor = null;
@@ -286,7 +292,7 @@ public class OrphanReaper
mergedFrom = mlink.getMfrom(); mergedFrom = mlink.getMfrom();
AVMDAOs.Instance().fMergeLinkDAO.delete(mlink); AVMDAOs.Instance().fMergeLinkDAO.delete(mlink);
} }
// Get all the nodes that have this node as ancestor. // Get all the nodes that have this node as ancestor.
List<HistoryLink> links = AVMDAOs.Instance().fHistoryLinkDAO.getByAncestor(node); List<HistoryLink> links = AVMDAOs.Instance().fHistoryLinkDAO.getByAncestor(node);
for (HistoryLink link : links) for (HistoryLink link : links)
@@ -306,13 +312,13 @@ public class OrphanReaper
link.getMto().setMergedFrom(ancestor); link.getMto().setMergedFrom(ancestor);
AVMDAOs.Instance().fMergeLinkDAO.delete(link); AVMDAOs.Instance().fMergeLinkDAO.delete(link);
} }
// Get rid of all properties belonging to this node. // Get rid of all properties belonging to this node.
AVMDAOs.Instance().fAVMNodeDAO.deleteProperties(node.getId()); AVMDAOs.Instance().fAVMNodeDAO.deleteProperties(node.getId());
// Get rid of all aspects belonging to this node. // Get rid of all aspects belonging to this node.
AVMDAOs.Instance().fAVMNodeDAO.deleteAspects(node.getId()); AVMDAOs.Instance().fAVMNodeDAO.deleteAspects(node.getId());
// Get rid of ACL. // Get rid of ACL.
DbAccessControlList acl = node.getAcl(); DbAccessControlList acl = node.getAcl();
node.setAcl(null); node.setAcl(null);

View File

@@ -18,6 +18,8 @@
*/ */
package org.alfresco.repo.workflow.jbpm; package org.alfresco.repo.workflow.jbpm;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
@@ -29,7 +31,10 @@ import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.jbpm.JbpmConfiguration; import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.JobSession;
import org.jbpm.job.Job; import org.jbpm.job.Job;
import org.jbpm.job.executor.JobExecutorThread; import org.jbpm.job.executor.JobExecutorThread;
@@ -55,6 +60,8 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
private long jobLockTTL = 0; private long jobLockTTL = 0;
private String jobLockToken = null; private String jobLockToken = null;
private JbpmConfiguration jbpmConfiguration;
@Override @Override
public void setActive(boolean isActive) public void setActive(boolean isActive)
{ {
@@ -71,6 +78,8 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
this.jbpmMaxLockTime = maxLockTime; this.jbpmMaxLockTime = maxLockTime;
this.jobLockTTL = jbpmMaxLockTime+(1000 * 60 * 10); this.jobLockTTL = jbpmMaxLockTime+(1000 * 60 * 10);
this.jbpmConfiguration = jbpmConfiguration;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -160,22 +169,124 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
protected void executeJob(Job job) protected void executeJob(final Job jobIn)
{ {
if ((!isActive) || (alfrescoJobExecutor.getTransactionService().isReadOnly())) if ((!isActive) || (alfrescoJobExecutor.getTransactionService().isReadOnly()))
{ {
return; return;
} }
// based on JBPM 3.3.1 (JobExecutorThread.executeJob)
// - wrap executeJob / deleteJob in Alfresco retries
// - add setRollbackOnly warnings
// - if Alfresco retries fail, attempt to set JBPM job exception/retries
try try
{ {
alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper().doInTransaction(new TransactionJob(job)); RetryingTransactionHelper tranHelper = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper();
tranHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try
{
JobSession jobSession = jbpmContext.getJobSession();
Job job = jobSession.loadJob(jobIn.getId());
if (logger.isTraceEnabled())
{
logger.trace("executing " + job);
}
if (job.execute(jbpmContext))
{
jobSession.deleteJob(job);
if (logger.isDebugEnabled())
{
logger.debug("executed and deleted: " + job);
}
}
// if this job is locked too long
long totalLockTimeInMillis = System.currentTimeMillis() - job.getLockTime().getTime();
if (totalLockTimeInMillis>jbpmMaxLockTime)
{
logger.warn("setRollbackOnly: exceeded maxLockTime ("+jbpmMaxLockTime+") " + job);
jbpmContext.setRollbackOnly();
}
}
finally
{
jbpmContext.close();
}
return null;
}
});
} }
catch (LockAcquisitionException e) catch (LockAcquisitionException e)
{ {
// ignore // ignore
jobLockToken = null; jobLockToken = null;
} }
catch (Exception e)
{
if (logger.isErrorEnabled())
{
logger.error("failed to execute " + jobIn, e);
}
if (!isPersistenceException(e))
{
try
{
final StringWriter memoryWriter = new StringWriter();
e.printStackTrace(new PrintWriter(memoryWriter));
RetryingTransactionHelper tranHelper = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper();
tranHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try
{
JobSession jobSession = jbpmContext.getJobSession();
final Job job = jobSession.loadJob(jobIn.getId());
if (logger.isDebugEnabled())
{
logger.debug("attempting to update exception/retries: " + job);
}
job.setException(memoryWriter.toString());
job.setRetries(job.getRetries()-1);
if (logger.isInfoEnabled())
{
logger.info("updated job exception and set to "+job.getRetries()+ " retries: " + jobIn);
}
}
finally
{
jbpmContext.close();
}
return null;
}
});
}
catch (Exception e2)
{
if (logger.isErrorEnabled())
{
logger.error("failed to update job exception/retries " + jobIn, e2);
}
}
}
}
} }
private String getExecutorLock() private String getExecutorLock()
@@ -254,37 +365,18 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
} }
} }
/** private boolean isPersistenceException(Throwable throwable)
* Helper class for holding Job reference
*
* @author davidc
*/
private class TransactionJob implements RetryingTransactionCallback<Object>
{ {
private Job job; do
/**
* Constructor
*
* @param job the job to execute
*/
public TransactionJob(Job job)
{ {
this.job = job; if (throwable instanceof HibernateException)
}
public Object execute() throws Throwable
{
refreshExecutorLock(jobLockToken);
AlfrescoJobExecutorThread.super.executeJob(job);
if (logger.isDebugEnabled())
{ {
logger.debug("executed job: "+job); return true;
} }
throwable = throwable.getCause();
return null; }
} while (throwable != null);
return false;
} }
} }