diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index 86b822260a..8807738d60 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -114,6 +114,9 @@ + + + @@ -330,6 +333,12 @@ + + + + + false + diff --git a/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java b/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java index 9e10f96733..4b619126d5 100644 --- a/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java +++ b/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java @@ -39,6 +39,7 @@ import org.alfresco.service.cmr.action.CancellableAction; import org.alfresco.service.cmr.action.ExecutionDetails; import org.alfresco.service.cmr.action.ExecutionSummary; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.transaction.TransactionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -56,6 +57,7 @@ public class ActionTrackingServiceImpl implements ActionTrackingService private static Log logger = LogFactory.getLog(ActionTrackingServiceImpl.class); private SimpleCache executingActionsCache; + private NodeService nodeService; private TransactionService transactionService; private RuntimeActionService runtimeActionService; @@ -78,6 +80,16 @@ public class ActionTrackingServiceImpl implements ActionTrackingService this.transactionService = transactionService; } + /** + * Set the node service + * + * @param nodeService the node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + /** * Set the runtime action service * @@ -139,7 +151,7 @@ public class ActionTrackingServiceImpl implements ActionTrackingService action.setExecutionFailureMessage(null); // Do we need to update the persisted details? - if (action.getNodeRef() != null) + if (action.getNodeRef() != null && nodeService.exists(action.getNodeRef())) { // Make sure we re-fetch the latest action details and save // this version back into the repository @@ -164,8 +176,15 @@ public class ActionTrackingServiceImpl implements ActionTrackingService { public Action doWork() throws Exception { - // Grab the latest version of the - // action + // Ensure the action persisted node still exists, and wasn't deleted + // between when it loaded running and now + if( !nodeService.exists(actionNode) ) + { + // Persisted node has gone, nothing to update + return null; + } + + // Grab the latest version of the action ActionImpl action = (ActionImpl) runtimeActionService .createAction(actionNode); diff --git a/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java b/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java index 066054b426..352332bbae 100644 --- a/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java @@ -24,12 +24,14 @@ import java.util.List; import java.util.Map; import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; /** * Add features action executor implementation. @@ -49,16 +51,29 @@ public class AddFeaturesActionExecuter extends ActionExecuterAbstractBase */ private NodeService nodeService; + /** Transaction Service, used for retrying operations */ + private TransactionService transactionService; + /** * Set the node service * - * @param nodeService the node service + * @param nodeService the node service */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } + /** + * Set the transaction service + * + * @param transactionService the transaction service + */ + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + /** * Adhoc properties are allowed for this executor */ @@ -71,32 +86,46 @@ public class AddFeaturesActionExecuter extends ActionExecuterAbstractBase /** * @see org.alfresco.repo.action.executer.ActionExecuter#execute(org.alfresco.service.cmr.repository.NodeRef, NodeRef) */ - public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) + public void executeImpl(final Action ruleAction, final NodeRef actionedUponNodeRef) { - if (this.nodeService.exists(actionedUponNodeRef) == true) - { - Map properties = new HashMap(); - QName aspectQName = null; - - Map paramValues = ruleAction.getParameterValues(); - for (Map.Entry entry : paramValues.entrySet()) - { - if (entry.getKey().equals(PARAM_ASPECT_NAME) == true) - { - aspectQName = (QName)entry.getValue(); - } - else - { - // Must be an adhoc property - QName propertyQName = QName.createQName(entry.getKey()); - Serializable propertyValue = entry.getValue(); - properties.put(propertyQName, propertyValue); - } - } - - // Add the aspect - this.nodeService.addAspect(actionedUponNodeRef, aspectQName, properties); - } + if (this.nodeService.exists(actionedUponNodeRef)) + { + transactionService.getRetryingTransactionHelper().doInTransaction( + new RetryingTransactionCallback() { + public Void execute() throws Throwable { + Map properties = new HashMap(); + QName aspectQName = null; + + if(! nodeService.exists(actionedUponNodeRef)) + { + // Node has gone away, skip + return null; + } + + // Build the aspect details + Map paramValues = ruleAction.getParameterValues(); + for (Map.Entry entry : paramValues.entrySet()) + { + if (entry.getKey().equals(PARAM_ASPECT_NAME) == true) + { + aspectQName = (QName)entry.getValue(); + } + else + { + // Must be an adhoc property + QName propertyQName = QName.createQName(entry.getKey()); + Serializable propertyValue = entry.getValue(); + properties.put(propertyQName, propertyValue); + } + } + + // Add the aspect + nodeService.addAspect(actionedUponNodeRef, aspectQName, properties); + return null; + } + } + ); + } } /**