mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-895: Can't Freeze record and folder witch contains record if updated rule to Freeze is set
* also dealt with exception that was not being handled by background job git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@55153 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -37,21 +37,32 @@ public abstract class AuditableActionExecuterAbstractBase extends ActionExecuter
|
|||||||
/** Indicates whether the action is auditable or not */
|
/** Indicates whether the action is auditable or not */
|
||||||
protected boolean auditable = true;
|
protected boolean auditable = true;
|
||||||
|
|
||||||
|
/** Application context */
|
||||||
protected ApplicationContext applicationContext;
|
protected ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
/** Records management audit service */
|
||||||
private RecordsManagementAuditService auditService;
|
private RecordsManagementAuditService auditService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param auditable true if auditable, false otherwise
|
||||||
|
*/
|
||||||
public void setAuditable(boolean auditable)
|
public void setAuditable(boolean auditable)
|
||||||
{
|
{
|
||||||
this.auditable = auditable;
|
this.auditable = auditable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||||
{
|
{
|
||||||
this.applicationContext = applicationContext;
|
this.applicationContext = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return records management audit service
|
||||||
|
*/
|
||||||
private RecordsManagementAuditService getAuditService()
|
private RecordsManagementAuditService getAuditService()
|
||||||
{
|
{
|
||||||
if (auditService == null)
|
if (auditService == null)
|
||||||
@@ -61,6 +72,9 @@ public abstract class AuditableActionExecuterAbstractBase extends ActionExecuter
|
|||||||
return auditService;
|
return auditService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#init()
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void init()
|
public void init()
|
||||||
{
|
{
|
||||||
|
@@ -46,6 +46,9 @@ public abstract class RMDispositionActionExecuterAbstractBase extends RMActionEx
|
|||||||
private static final String MSG_NEXT_DISP_NOT_SET = "rm.action.next-disp-not-set";
|
private static final String MSG_NEXT_DISP_NOT_SET = "rm.action.next-disp-not-set";
|
||||||
private static final String MSG_NOT_NEXT_DISP = "rm.action.not-next-disp";
|
private static final String MSG_NOT_NEXT_DISP = "rm.action.not-next-disp";
|
||||||
private static final String MSG_NOT_RECORD_FOLDER = "rm.action.not-record-folder";
|
private static final String MSG_NOT_RECORD_FOLDER = "rm.action.not-record-folder";
|
||||||
|
|
||||||
|
/** Parameter value indicating whether we should be doing non-error raising state checks */
|
||||||
|
public static final String PARAM_NO_ERROR_CHECK = "rm.no-error-check";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All children of this implementation are disposition actions.
|
* All children of this implementation are disposition actions.
|
||||||
@@ -97,91 +100,100 @@ public abstract class RMDispositionActionExecuterAbstractBase extends RMActionEx
|
|||||||
@Override
|
@Override
|
||||||
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
||||||
{
|
{
|
||||||
//
|
NodeRef nextDispositionActionNodeRef = getNextDispostionAction(actionedUponNodeRef);
|
||||||
NodeRef nextDispositionActionNodeRef = getNextDispostionAction(actionedUponNodeRef);
|
|
||||||
|
// determine whether we should be raising errors during state checking or not
|
||||||
|
boolean checkError = true;
|
||||||
|
Boolean checkErrorValue = (Boolean)action.getParameterValue(PARAM_NO_ERROR_CHECK);
|
||||||
|
if (checkErrorValue != null)
|
||||||
|
{
|
||||||
|
checkError = checkErrorValue.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
// Check the validity of the action (is it the next action, are we dealing with the correct type of object for
|
// Check the validity of the action (is it the next action, are we dealing with the correct type of object for
|
||||||
// the disposition level?
|
// the disposition level?
|
||||||
DispositionSchedule di = checkDispositionActionExecutionValidity(actionedUponNodeRef, nextDispositionActionNodeRef, true);
|
DispositionSchedule di = checkDispositionActionExecutionValidity(actionedUponNodeRef, nextDispositionActionNodeRef, checkError);
|
||||||
|
if (di != null)
|
||||||
// Check the eligibility of the action
|
|
||||||
if (checkEligibility(actionedUponNodeRef) == false ||
|
|
||||||
dispositionService.isNextDispositionActionEligible(actionedUponNodeRef) == true)
|
|
||||||
{
|
{
|
||||||
if (di.isRecordLevelDisposition() == true)
|
// Check the eligibility of the action
|
||||||
|
if (checkEligibility(actionedUponNodeRef) == false ||
|
||||||
|
dispositionService.isNextDispositionActionEligible(actionedUponNodeRef) == true)
|
||||||
{
|
{
|
||||||
// Check that we do indeed have a record
|
if (di.isRecordLevelDisposition() == true)
|
||||||
if (recordService.isRecord(actionedUponNodeRef) == true)
|
|
||||||
{
|
{
|
||||||
// Can only execute disposition action on record if declared
|
// Check that we do indeed have a record
|
||||||
if (recordService.isDeclared(actionedUponNodeRef) == true)
|
if (recordService.isRecord(actionedUponNodeRef) == true)
|
||||||
{
|
{
|
||||||
// Indicate that the disposition action is underway
|
// Can only execute disposition action on record if declared
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_AT, new Date());
|
if (recordService.isDeclared(actionedUponNodeRef) == true)
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_BY, AuthenticationUtil.getRunAsUser());
|
|
||||||
|
|
||||||
// Execute record level disposition
|
|
||||||
executeRecordLevelDisposition(action, actionedUponNodeRef);
|
|
||||||
|
|
||||||
if (this.nodeService.exists(nextDispositionActionNodeRef) == true &&
|
|
||||||
getSetDispositionActionComplete() == true)
|
|
||||||
{
|
{
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_AT, new Date());
|
// Indicate that the disposition action is underway
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_BY, AuthenticationUtil.getRunAsUser());
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_AT, new Date());
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_BY, AuthenticationUtil.getRunAsUser());
|
||||||
|
|
||||||
|
// Execute record level disposition
|
||||||
|
executeRecordLevelDisposition(action, actionedUponNodeRef);
|
||||||
|
|
||||||
|
if (this.nodeService.exists(nextDispositionActionNodeRef) == true &&
|
||||||
|
getSetDispositionActionComplete() == true)
|
||||||
|
{
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_AT, new Date());
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_BY, AuthenticationUtil.getRunAsUser());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_RECORD_NOT_DECLARED, getName(), actionedUponNodeRef.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_RECORD_NOT_DECLARED, getName(), actionedUponNodeRef.toString()));
|
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_EXPECTED_RECORD_LEVEL, getName(), actionedUponNodeRef.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_EXPECTED_RECORD_LEVEL, getName(), actionedUponNodeRef.toString()));
|
if (this.recordsManagementService.isRecordFolder(actionedUponNodeRef) == true)
|
||||||
|
{
|
||||||
|
if (this.recordsManagementService.isRecordFolderDeclared(actionedUponNodeRef) == true)
|
||||||
|
{
|
||||||
|
// Indicate that the disposition action is underway
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_AT, new Date());
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_BY, AuthenticationUtil.getRunAsUser());
|
||||||
|
|
||||||
|
executeRecordFolderLevelDisposition(action, actionedUponNodeRef);
|
||||||
|
|
||||||
|
// Indicate that the disposition action is compelte
|
||||||
|
if (this.nodeService.exists(nextDispositionActionNodeRef) == true &&
|
||||||
|
getSetDispositionActionComplete() == true)
|
||||||
|
{
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_AT, new Date());
|
||||||
|
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_BY, AuthenticationUtil.getRunAsUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_ALL_RECORDS_DECLARED, getName(), actionedUponNodeRef.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_RECORD_FOLDER, getName(), actionedUponNodeRef.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.nodeService.exists(actionedUponNodeRef) == true && getSetDispositionActionComplete() == true)
|
||||||
|
{
|
||||||
|
// Update the disposition schedule
|
||||||
|
updateNextDispositionAction(actionedUponNodeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (this.recordsManagementService.isRecordFolder(actionedUponNodeRef) == true)
|
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_ELIGIBLE, getName(), actionedUponNodeRef.toString()));
|
||||||
{
|
|
||||||
if (this.recordsManagementService.isRecordFolderDeclared(actionedUponNodeRef) == true)
|
|
||||||
{
|
|
||||||
// Indicate that the disposition action is underway
|
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_AT, new Date());
|
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_BY, AuthenticationUtil.getRunAsUser());
|
|
||||||
|
|
||||||
executeRecordFolderLevelDisposition(action, actionedUponNodeRef);
|
|
||||||
|
|
||||||
// Indicate that the disposition action is compelte
|
|
||||||
if (this.nodeService.exists(nextDispositionActionNodeRef) == true &&
|
|
||||||
getSetDispositionActionComplete() == true)
|
|
||||||
{
|
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_AT, new Date());
|
|
||||||
this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_COMPLETED_BY, AuthenticationUtil.getRunAsUser());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_ALL_RECORDS_DECLARED, getName(), actionedUponNodeRef.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_RECORD_FOLDER, getName(), actionedUponNodeRef.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.nodeService.exists(actionedUponNodeRef) == true && getSetDispositionActionComplete() == true)
|
|
||||||
{
|
|
||||||
// Update the disposition schedule
|
|
||||||
updateNextDispositionAction(actionedUponNodeRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_ELIGIBLE, getName(), actionedUponNodeRef.toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,8 +57,11 @@ public class FreezeAction extends RMActionExecuterAbstractBase
|
|||||||
if (nodeService.exists(actionedUponNodeRef) == true &&
|
if (nodeService.exists(actionedUponNodeRef) == true &&
|
||||||
nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_PENDING_DELETE) == false &&
|
nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_PENDING_DELETE) == false &&
|
||||||
(recordService.isRecord(actionedUponNodeRef) == true ||
|
(recordService.isRecord(actionedUponNodeRef) == true ||
|
||||||
recordsManagementService.isRecordFolder(actionedUponNodeRef) == true))
|
recordsManagementService.isRecordFolder(actionedUponNodeRef) == true) &&
|
||||||
|
freezeService.isFrozen(actionedUponNodeRef) == false)
|
||||||
{
|
{
|
||||||
|
System.out.println("I am trying to freeze " + actionedUponNodeRef.toString());
|
||||||
|
|
||||||
freezeService.freeze((String) action.getParameterValue(PARAM_REASON), actionedUponNodeRef);
|
freezeService.freeze((String) action.getParameterValue(PARAM_REASON), actionedUponNodeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,13 @@
|
|||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.job;
|
package org.alfresco.module.org_alfresco_module_rm.job;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService;
|
import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
@@ -73,65 +78,77 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
|
|||||||
*/
|
*/
|
||||||
public void executeImpl()
|
public void executeImpl()
|
||||||
{
|
{
|
||||||
logger.debug("Job Starting");
|
try
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("+TYPE:\"rma:dispositionAction\" ");
|
|
||||||
sb.append("+(@rma\\:dispositionAction:(\"cutoff\" OR \"retain\"))");
|
|
||||||
sb.append("+ISNULL:\"rma:dispositionActionCompletedAt\" ");
|
|
||||||
sb.append("+( ");
|
|
||||||
sb.append("@rma\\:dispositionEventsEligible:true ");
|
|
||||||
sb.append("OR @rma\\:dispositionAsOf:[MIN TO NOW] ");
|
|
||||||
sb.append(") ");
|
|
||||||
|
|
||||||
String query = sb.toString();
|
|
||||||
|
|
||||||
ResultSet results = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
|
|
||||||
SearchService.LANGUAGE_LUCENE, query);
|
|
||||||
List<NodeRef> resultNodes = results.getNodeRefs();
|
|
||||||
results.close();
|
|
||||||
|
|
||||||
|
|
||||||
for (NodeRef node : resultNodes)
|
|
||||||
{
|
{
|
||||||
final NodeRef currentNode = node;
|
logger.debug("Job Starting");
|
||||||
|
|
||||||
RetryingTransactionCallback<Boolean> processTranCB = new RetryingTransactionCallback<Boolean>()
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("+TYPE:\"rma:dispositionAction\" ");
|
||||||
|
sb.append("+(@rma\\:dispositionAction:(\"cutoff\" OR \"retain\"))");
|
||||||
|
sb.append("+ISNULL:\"rma:dispositionActionCompletedAt\" ");
|
||||||
|
sb.append("+( ");
|
||||||
|
sb.append("@rma\\:dispositionEventsEligible:true ");
|
||||||
|
sb.append("OR @rma\\:dispositionAsOf:[MIN TO NOW] ");
|
||||||
|
sb.append(") ");
|
||||||
|
|
||||||
|
String query = sb.toString();
|
||||||
|
|
||||||
|
ResultSet results = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
|
||||||
|
SearchService.LANGUAGE_LUCENE, query);
|
||||||
|
List<NodeRef> resultNodes = results.getNodeRefs();
|
||||||
|
results.close();
|
||||||
|
|
||||||
|
|
||||||
|
for (NodeRef node : resultNodes)
|
||||||
{
|
{
|
||||||
public Boolean execute() throws Throwable
|
final NodeRef currentNode = node;
|
||||||
|
|
||||||
|
RetryingTransactionCallback<Boolean> processTranCB = new RetryingTransactionCallback<Boolean>()
|
||||||
{
|
{
|
||||||
final String dispAction = (String) nodeService.getProperty(currentNode,
|
public Boolean execute() throws Throwable
|
||||||
RecordsManagementModel.PROP_DISPOSITION_ACTION);
|
|
||||||
|
|
||||||
// Run "retain" and "cutoff" actions.
|
|
||||||
|
|
||||||
if (dispAction != null)
|
|
||||||
{
|
{
|
||||||
if (dispAction.equalsIgnoreCase("cutoff") ||
|
final String dispAction = (String) nodeService.getProperty(currentNode,
|
||||||
dispAction.equalsIgnoreCase("retain"))
|
RecordsManagementModel.PROP_DISPOSITION_ACTION);
|
||||||
|
|
||||||
|
// Run "retain" and "cutoff" actions.
|
||||||
|
|
||||||
|
if (dispAction != null)
|
||||||
{
|
{
|
||||||
ChildAssociationRef parent = nodeService.getPrimaryParent(currentNode);
|
if (dispAction.equalsIgnoreCase("cutoff") ||
|
||||||
if (parent.getTypeQName().equals(RecordsManagementModel.ASSOC_NEXT_DISPOSITION_ACTION))
|
dispAction.equalsIgnoreCase("retain"))
|
||||||
{
|
{
|
||||||
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction);
|
ChildAssociationRef parent = nodeService.getPrimaryParent(currentNode);
|
||||||
if (logger.isDebugEnabled())
|
if (parent.getTypeQName().equals(RecordsManagementModel.ASSOC_NEXT_DISPOSITION_ACTION))
|
||||||
{
|
{
|
||||||
logger.debug("Processed action: " + dispAction + "on" + parent);
|
Map<String, Serializable> props = new HashMap<String, Serializable>(1);
|
||||||
|
props.put(RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK, Boolean.FALSE);
|
||||||
|
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props);
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Processed action: " + dispAction + "on" + parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
return Boolean.TRUE;
|
};
|
||||||
}
|
|
||||||
};
|
/**
|
||||||
|
* Now do the work, one action in each transaction
|
||||||
/**
|
*/
|
||||||
* Now do the work, one action in each transaction
|
retryingTransactionHelper.doInTransaction(processTranCB);
|
||||||
*/
|
}
|
||||||
retryingTransactionHelper.doInTransaction(processTranCB);
|
|
||||||
|
logger.debug("Job Finished");
|
||||||
|
}
|
||||||
|
catch (AlfrescoRuntimeException exception)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Job Finished");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user