Merge from HEAD to BRANCHES/V2.1.0.x

* 61170 - RM-1413: DispositionLifecycleJobExecuter does not execute the disposition action



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.1.0.x@68568 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-05-02 03:31:42 +00:00
parent 5510969068
commit f644f97ebe
3 changed files with 142 additions and 54 deletions

View File

@@ -18,4 +18,12 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl=debug #log4j.logger.org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl=debug
#log4j.logger.org.springframework.extensions.webscripts.ScriptDebugger=on #log4j.logger.org.springframework.extensions.webscripts.ScriptDebugger=on
#
# RM Audit service debug
#
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService=debug #log4j.logger.org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService=debug
#
# Job debug
#
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug

View File

@@ -72,6 +72,15 @@
<bean id="dispositionLifecycleJobExecuter" <bean id="dispositionLifecycleJobExecuter"
class="org.alfresco.module.org_alfresco_module_rm.job.DispositionLifecycleJobExecuter" class="org.alfresco.module.org_alfresco_module_rm.job.DispositionLifecycleJobExecuter"
parent="baseRMJobExecuter"> parent="baseRMJobExecuter">
<!-- list of disposition actions to automatically execute when eligible -->
<property name="dispositionActions">
<list>
<value>cutoff</value>
<value>retain</value>
</list>
</property>
<property name="nodeService" ref="nodeService" /> <property name="nodeService" ref="nodeService" />
<property name="searchService" ref="searchService" /> <property name="searchService" ref="searchService" />
<property name="recordsManagementActionService" ref="recordsManagementActionService" /> <property name="recordsManagementActionService" ref="recordsManagementActionService" />
@@ -85,8 +94,16 @@
<ref bean="schedulerFactory" /> <ref bean="schedulerFactory" />
</property> </property>
<property name="cronExpression"> <property name="cronExpression">
<!-- run at 3am -->
<!-- <value>0 30 3 * * ?</value> --> <!-- <value>0 30 3 * * ?</value> -->
<value>0 0/15 * * * ?</value>
<!-- run every 15 minutes -->
<!-- <value>0 0/15 * * * ?</value> -->
<!-- run every 30 seconds -->
<value>0/30 * * * * ?</value>
</property> </property>
</bean> </bean>

View File

@@ -40,39 +40,111 @@ import org.apache.commons.logging.LogFactory;
/** /**
* The Disposition Lifecycle Job Finds all disposition action nodes which are * The Disposition Lifecycle Job Finds all disposition action nodes which are
* for "retain" or "cutOff" actions Where asOf > now OR * for disposition actions specified Where asOf > now OR
* dispositionEventsEligible = true; * dispositionEventsEligible = true;
* *
* Runs the cut off or retain action for * Runs the cut off or retain action for
* elligible records. * eligible records.
* *
* @author mrogers * @author mrogers
* @author Roy Wetherall
*/ */
public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecuter public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecuter
{ {
/** logger */
private static Log logger = LogFactory.getLog(DispositionLifecycleJobExecuter.class); private static Log logger = LogFactory.getLog(DispositionLifecycleJobExecuter.class);
/** list of disposition actions to automatically execute */
private List<String> dispositionActions;
/** query string */
private String query;
/** records management action service */
private RecordsManagementActionService recordsManagementActionService; private RecordsManagementActionService recordsManagementActionService;
/** node service */
private NodeService nodeService; private NodeService nodeService;
/** search service */
private SearchService searchService; private SearchService searchService;
/**
* List of disposition actions to automatically execute when eligible.
*
* @param dispositionActions disposition actions
*/
public void setDispositionActions(List<String> dispositionActions)
{
this.dispositionActions = dispositionActions;
}
/**
* @param recordsManagementActionService records management action service
*/
public void setRecordsManagementActionService(RecordsManagementActionService recordsManagementActionService) public void setRecordsManagementActionService(RecordsManagementActionService recordsManagementActionService)
{ {
this.recordsManagementActionService = recordsManagementActionService; this.recordsManagementActionService = recordsManagementActionService;
} }
/**
* @param nodeService node service
*/
public void setNodeService(NodeService nodeService) public void setNodeService(NodeService nodeService)
{ {
this.nodeService = nodeService; this.nodeService = nodeService;
} }
/**
* @param searchService search service
*/
public void setSearchService(SearchService searchService) public void setSearchService(SearchService searchService)
{ {
this.searchService = searchService; this.searchService = searchService;
} }
/**
* Get the search query string.
*
* @return job query string
*/
private String getQuery()
{
if (query == null)
{
StringBuilder sb = new StringBuilder();
sb.append("+TYPE:\"rma:dispositionAction\" ");
sb.append("+(@rma\\:dispositionAction:(");
boolean bFirst = true;
for (String dispositionAction : dispositionActions)
{
if (bFirst)
{
bFirst = false;
}
else
{
sb.append(" OR ");
}
sb.append("\"").append(dispositionAction).append("\"");
}
sb.append("))");
sb.append("+ISNULL:\"rma:dispositionActionCompletedAt\" ");
sb.append("+( ");
sb.append("@rma\\:dispositionEventsEligible:true ");
sb.append("OR @rma\\:dispositionAsOf:[MIN TO NOW] ");
sb.append(") ");
query = sb.toString();
}
return query;
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute() * @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute()
*/ */
@@ -82,66 +154,57 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
{ {
logger.debug("Job Starting"); logger.debug("Job Starting");
StringBuilder sb = new StringBuilder(); if (dispositionActions != null && !dispositionActions.isEmpty())
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; // execute search
ResultSet results = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_LUCENE, getQuery());
List<NodeRef> resultNodes = results.getNodeRefs();
results.close();
RetryingTransactionCallback<Boolean> processTranCB = new RetryingTransactionCallback<Boolean>() if (logger.isDebugEnabled())
{ {
public Boolean execute() throws Throwable logger.debug("Processing " + resultNodes.size() + " nodes");
}
// process search results
for (NodeRef node : resultNodes)
{
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, RecordsManagementModel.PROP_DISPOSITION_ACTION);
dispAction.equalsIgnoreCase("retain"))
// Run disposition action
if (dispAction != null && dispositionActions.contains(dispAction))
{ {
ChildAssociationRef parent = nodeService.getPrimaryParent(currentNode); ChildAssociationRef parent = nodeService.getPrimaryParent(currentNode);
if (parent.getTypeQName().equals(RecordsManagementModel.ASSOC_NEXT_DISPOSITION_ACTION)) if (parent.getTypeQName().equals(RecordsManagementModel.ASSOC_NEXT_DISPOSITION_ACTION))
{ {
Map<String, Serializable> props = new HashMap<String, Serializable>(1); Map<String, Serializable> props = new HashMap<String, Serializable>(1);
props.put(RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK, Boolean.FALSE); props.put(RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK, Boolean.FALSE);
// execute disposition action
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props); recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Processed action: " + dispAction + "on" + parent); logger.debug("Processed action: " + dispAction + "on" + parent);
} }
} }
return null;
} }
return Boolean.TRUE;
} }
return Boolean.TRUE; };
// if exists
if (nodeService.exists(currentNode))
{
retryingTransactionHelper.doInTransaction(processTranCB);
} }
};
/**
* Now do the work, one action in each transaction
*/
if (nodeService.exists(currentNode) == false)
{
retryingTransactionHelper.doInTransaction(processTranCB);
} }
} }
@@ -149,7 +212,7 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
} }
catch (AlfrescoRuntimeException exception) catch (AlfrescoRuntimeException exception)
{ {
if (logger.isDebugEnabled() == true) if (logger.isDebugEnabled())
{ {
logger.debug(exception); logger.debug(exception);
} }