Merged BRANCHES/V3.4 to HEAD:

24356: It's possible for a persisted action to be removed during the transaction, so have the ActionTrackingService ensure the node still exists before doing the async update of the details (ALF-5745)
   24374: ALF-5744 - Retry the add aspect to avoid failures due to concurrent node updates


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@24931 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Nick Burch
2011-01-19 15:25:28 +00:00
parent 2b8e3837ce
commit 8c500a3cd8
3 changed files with 86 additions and 29 deletions

View File

@@ -114,6 +114,9 @@
<property name="transactionService">
<ref bean="TransactionService" />
</property>
<property name="nodeService">
<ref bean="NodeService" />
</property>
<property name="runtimeActionService">
<ref bean="actionService" />
</property>
@@ -330,6 +333,12 @@
<property name="nodeService">
<ref bean="NodeService" />
</property>
<property name="transactionService">
<ref bean="TransactionService" />
</property>
<property name="ignoreLock">
<value>false</value>
</property>
</bean>
<bean id="remove-features" class="org.alfresco.repo.action.executer.RemoveFeaturesActionExecuter" parent="action-executer">

View File

@@ -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<String, ExecutionDetails> 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);

View File

@@ -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,6 +51,9 @@ public class AddFeaturesActionExecuter extends ActionExecuterAbstractBase
*/
private NodeService nodeService;
/** Transaction Service, used for retrying operations */
private TransactionService transactionService;
/**
* Set the node service
*
@@ -59,6 +64,16 @@ public class AddFeaturesActionExecuter extends ActionExecuterAbstractBase
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,13 +86,23 @@ 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)
if (this.nodeService.exists(actionedUponNodeRef))
{
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
QName aspectQName = null;
if(! nodeService.exists(actionedUponNodeRef))
{
// Node has gone away, skip
return null;
}
// Build the aspect details
Map<String, Serializable> paramValues = ruleAction.getParameterValues();
for (Map.Entry<String, Serializable> entry : paramValues.entrySet())
{
@@ -95,7 +120,11 @@ public class AddFeaturesActionExecuter extends ActionExecuterAbstractBase
}
// Add the aspect
this.nodeService.addAspect(actionedUponNodeRef, aspectQName, properties);
nodeService.addAspect(actionedUponNodeRef, aspectQName, properties);
return null;
}
}
);
}
}