RM-6941 Changes for retention action on frozen nodes [ags]

This commit is contained in:
bdwiwedi
2021-08-01 22:25:27 +05:30
parent 28eaa8c2f8
commit e1313d7227
8 changed files with 76 additions and 76 deletions

View File

@@ -67,7 +67,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
/** /**
* API tests to check actions on frozen content * API tests to check actions on frozen content
* *
@@ -309,11 +309,11 @@ public class PreventActionsOnFrozenContentTests extends BaseRMRestTest
STEP("Execute the retain action"); STEP("Execute the retain action");
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getPassword(), record.getName(), rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getPassword(), record.getName(),
RM_ACTIONS.END_RETENTION); RM_ACTIONS.END_RETENTION, null, SC_INTERNAL_SERVER_ERROR);
STEP("Check the record search disposition properties"); STEP("Check the record search disposition properties");
Record recordUpdated = getRestAPIFactory().getRecordsAPI().getRecord(record.getId()); Record recordUpdated = getRestAPIFactory().getRecordsAPI().getRecord(record.getId());
assertTrue(recordUpdated.getProperties().getRecordSearchDispositionActionName().contains(RM_ACTIONS.DESTROY.getAction())); assertTrue(recordUpdated.getProperties().getRecordSearchDispositionActionName().contains(RM_ACTIONS.END_RETENTION.getAction()));
assertTrue(recordUpdated.getProperties().getRecordSearchDispositionPeriod().contains("immediately")); assertTrue(recordUpdated.getProperties().getRecordSearchDispositionPeriod().contains("immediately"));
} }

View File

@@ -45,4 +45,4 @@ rm.action.create.transfer.container.child-error-message=You can't create items i
rm.action.create.transfer.child-error-message=You can't create items in Transfer Folders. rm.action.create.transfer.child-error-message=You can't create items in Transfer Folders.
rm.action.create.record.folder.child-error-message=You can only create records in record folders and this was a {0}. rm.action.create.record.folder.child-error-message=You can only create records in record folders and this was a {0}.
rm.action.transfer-non-editable=You can't edit transfer folder or container metadata. rm.action.transfer-non-editable=You can't edit transfer folder or container metadata.
rm.action.node.frozen.error-message=unable to perform action {0} because node is frozen or has frozen children

View File

@@ -80,9 +80,6 @@
<property name="searchService" ref="searchService" /> <property name="searchService" ref="searchService" />
<property name="personService" ref="personService" /> <property name="personService" ref="personService" />
<property name="recordsManagementActionService" ref="recordsManagementActionService" /> <property name="recordsManagementActionService" ref="recordsManagementActionService" />
<property name="recordFolderService" ref="RecordFolderService" />
<property name="recordService" ref="RecordService" />
<property name="freezeService" ref="FreezeService" />
<property name="batchSize" value="${rm.dispositionlifecycletrigger.batchsize}"/> <property name="batchSize" value="${rm.dispositionlifecycletrigger.batchsize}"/>
</bean> </bean>

View File

@@ -112,6 +112,7 @@
<property name="filePlanService" ref="FilePlanService" /> <property name="filePlanService" ref="FilePlanService" />
<property name="recordFolderService" ref="RecordFolderService"/> <property name="recordFolderService" ref="RecordFolderService"/>
<property name="recordService" ref="RecordService"/> <property name="recordService" ref="RecordService"/>
<property name="freezeService" ref="FreezeService"/>
<property name="transactionService" ref="transactionService" /> <property name="transactionService" ref="transactionService" />
</bean> </bean>
@@ -695,6 +696,13 @@
init-method="init" depends-on="org_alfresco_module_rm_resourceBundles"> init-method="init" depends-on="org_alfresco_module_rm_resourceBundles">
<property name="policyComponent" ref="policyComponent"/> <property name="policyComponent" ref="policyComponent"/>
<property name="nodeService" ref="nodeService"/> <property name="nodeService" ref="nodeService"/>
<!-- list of disposition actions to automatically execute when eligible -->
<property name="retentionActions">
<list>
<value>cutoff</value>
<value>retain</value>
</list>
</property>
</bean> </bean>
<bean id="RecordsManagementActionService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="RecordsManagementActionService" class="org.springframework.aop.framework.ProxyFactoryBean">

View File

@@ -39,6 +39,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.BeforeRMActionExecution; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.BeforeRMActionExecution;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.OnRMActionExecution; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.OnRMActionExecution;
import org.alfresco.module.org_alfresco_module_rm.util.PoliciesUtil; import org.alfresco.module.org_alfresco_module_rm.util.PoliciesUtil;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.ClassPolicyDelegate;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -47,6 +48,7 @@ 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.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.beans.factory.annotation.Autowired;
/** /**
* Records Management Action Service Implementation * Records Management Action Service Implementation
@@ -58,9 +60,9 @@ public class RecordsManagementActionServiceImpl implements RecordsManagementActi
/** I18N */ /** I18N */
private static final String MSG_NOT_DEFINED = "rm.action.not-defined"; private static final String MSG_NOT_DEFINED = "rm.action.not-defined";
private static final String MSG_NO_IMPLICIT_NODEREF = "rm.action.no-implicit-noderef"; private static final String MSG_NO_IMPLICIT_NODEREF = "rm.action.no-implicit-noderef";
private static final String MSG_NODE_FROZEN = "rm.action.node.frozen.error-message";
/** Logger */ /** Logger */
private static Log logger = LogFactory.getLog(RecordsManagementActionServiceImpl.class); private static final Log logger = LogFactory.getLog(RecordsManagementActionServiceImpl.class);
/** Registered records management actions */ /** Registered records management actions */
private Map<String, RecordsManagementAction> rmActions = new HashMap<>(13); private Map<String, RecordsManagementAction> rmActions = new HashMap<>(13);
@@ -78,6 +80,16 @@ public class RecordsManagementActionServiceImpl implements RecordsManagementActi
private ClassPolicyDelegate<BeforeRMActionExecution> beforeRMActionExecutionDelegate; private ClassPolicyDelegate<BeforeRMActionExecution> beforeRMActionExecutionDelegate;
private ClassPolicyDelegate<OnRMActionExecution> onRMActionExecutionDelegate; private ClassPolicyDelegate<OnRMActionExecution> onRMActionExecutionDelegate;
@Autowired
private DispositionService dispositionService;
/** list of disposition actions to automatically execute */
private List<String> retentionActions;
public void setRetentionActions(List<String> retentionActions) {
this.retentionActions = retentionActions;
}
/** /**
* @return Policy component * @return Policy component
*/ */
@@ -285,6 +297,16 @@ public class RecordsManagementActionServiceImpl implements RecordsManagementActi
throw new AlfrescoRuntimeException(msg); throw new AlfrescoRuntimeException(msg);
} }
if (dispositionService.isFrozenOrHasFrozenChildren(nodeRef) && retentionActions.contains(name.toLowerCase())) {
String msg = I18NUtil.getMessage(MSG_NODE_FROZEN, rmAction.getName());
if (logger.isDebugEnabled())
{
logger.debug(msg);
}
throw new AlfrescoRuntimeException(msg);
}
// Execute action // Execute action
invokeBeforeRMActionExecution(nodeRef, name, parameters); invokeBeforeRMActionExecution(nodeRef, name, parameters);
RecordsManagementActionResult result = rmAction.execute(nodeRef, parameters); RecordsManagementActionResult result = rmAction.execute(nodeRef, parameters);

View File

@@ -288,4 +288,12 @@ public interface DispositionService
* @param record * @param record
*/ */
void recalculateNextDispositionStep(NodeRef record); void recalculateNextDispositionStep(NodeRef record);
/**
* Check given node or its children are frozen
* The node should be record or record folder for retention schedule
*
* @param nodeRef
*/
boolean isFrozenOrHasFrozenChildren(NodeRef nodeRef);
} }

View File

@@ -59,7 +59,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -117,6 +116,9 @@ public class DispositionServiceImpl extends ServiceBaseImpl
/** Record Service */ /** Record Service */
private RecordService recordService; private RecordService recordService;
/** Freeze Service */
private FreezeService freezeService;
/** Transaction service */ /** Transaction service */
private TransactionService transactionService; private TransactionService transactionService;
@@ -189,6 +191,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl
this.recordService = recordService; this.recordService = recordService;
} }
/**
* @param freezeService freeze service
*/
public void setFreezeService(FreezeService freezeService)
{
this.freezeService = freezeService;
}
/** /**
* @param transactionService transaction service * @param transactionService transaction service
*/ */
@@ -1458,4 +1468,24 @@ public class DispositionServiceImpl extends ServiceBaseImpl
return new NextActionFromDisposition(dispositionNodeRef, newAction, return new NextActionFromDisposition(dispositionNodeRef, newAction,
newDispositionActionName, newDispositionActionDateAsOf, WriteMode.DATE_AND_NAME); newDispositionActionName, newDispositionActionDateAsOf, WriteMode.DATE_AND_NAME);
} }
/**
* Helper method to determine if a node is frozen or has frozen children
*
* @param nodeRef Node to be checked
* @return <code>true</code> if the node is frozen or has frozen children, <code>false</code> otherwise
*/
@Override
public boolean isFrozenOrHasFrozenChildren(NodeRef nodeRef)
{
if (recordFolderService.isRecordFolder(nodeRef))
{
return freezeService.isFrozen(nodeRef) || freezeService.hasFrozenChildren(nodeRef);
}
else if (recordService.isRecord(nodeRef))
{
return freezeService.isFrozen(nodeRef);
}
return Boolean.FALSE;
}
} }

View File

@@ -30,15 +30,11 @@ package org.alfresco.module.org_alfresco_module_rm.job;
import static org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK; import static org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
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.freeze.FreezeService;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -61,7 +57,7 @@ import org.apache.commons.logging.LogFactory;
public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecuter public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecuter
{ {
/** logger */ /** logger */
private static Log logger = LogFactory.getLog(DispositionLifecycleJobExecuter.class); private static final Log logger = LogFactory.getLog(DispositionLifecycleJobExecuter.class);
/** batching properties */ /** batching properties */
private int batchSize; private int batchSize;
@@ -85,15 +81,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
/** person service */ /** person service */
private PersonService personService; private PersonService personService;
/** freeze service */
private FreezeService freezeService;
/** record service */
private RecordService recordService;
/** record folder service */
private RecordFolderService recordFolderService;
/** /**
* List of disposition actions to automatically execute when eligible. * List of disposition actions to automatically execute when eligible.
* *
@@ -133,30 +120,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
this.searchService = searchService; this.searchService = searchService;
} }
/**
* @param freezeService freeze service
*/
public void setFreezeService(FreezeService freezeService)
{
this.freezeService = freezeService;
}
/**
* @param recordService record service
*/
public void setRecordService(RecordService recordService)
{
this.recordService = recordService;
}
/**
* @param recordFolderService record folder service
*/
public void setRecordFolderService(RecordFolderService recordFolderService)
{
this.recordFolderService = recordFolderService;
}
/** /**
* Get the search query string. * Get the search query string.
* *
@@ -299,15 +262,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
} }
Map<String, Serializable> props = Map.of(PARAM_NO_ERROR_CHECK, false); Map<String, Serializable> props = Map.of(PARAM_NO_ERROR_CHECK, false);
if (isFrozenOrHasFrozenChildren(parent.getParentRef()))
{
if (logger.isDebugEnabled()) {
logger.debug("unable to perform action " + dispAction +
" because node is frozen or has frozen children");
}
continue;
}
try try
{ {
// execute disposition action // execute disposition action
@@ -332,25 +286,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
retryingTransactionHelper.doInTransaction(processTranCB, false, true); retryingTransactionHelper.doInTransaction(processTranCB, false, true);
} }
/**
* Helper method to determine if a node is frozen or has frozen children
*
* @param nodeRef Node to be checked
* @return <code>true</code> if the node is frozen or has frozen children, <code>false</code> otherwise
*/
private boolean isFrozenOrHasFrozenChildren(NodeRef nodeRef)
{
if (recordFolderService.isRecordFolder(nodeRef))
{
return freezeService.isFrozen(nodeRef) || freezeService.hasFrozenChildren(nodeRef);
}
if (recordService.isRecord(nodeRef))
{
return freezeService.isFrozen(nodeRef);
}
throw new AlfrescoRuntimeException("The nodeRef '" + nodeRef + "' is neither a record nor a record folder.");
}
public PersonService getPersonService() public PersonService getPersonService()
{ {
return personService; return personService;