mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM Performance Improvements
* general file plan browse rendering in around half the previously recorded times for around 500 records (need to scale up) * unessesary bottle neck removed from record detail page rendering (see RM-1461) * other general improvements * TODO .. hasFrozenChildren, getNextDisposition, TransferNodeIndicator, HeldBy .. all traverse up or down record/record folder hierarchy in ways that don't scale * fix to disposition lifecycle job that failed all when one failed .. this explains why the job appeared not to work on occasion git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@74458 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
<bean id="capabilityCondition.base"
|
<bean id="capabilityCondition.base"
|
||||||
abstract="true">
|
abstract="true">
|
||||||
<property name="permissionService" ref="PermissionService" />
|
<property name="permissionService" ref="permissionService" /> <!-- use lower case service to enhance performance -->
|
||||||
<property name="nodeService" ref="NodeService" />
|
<property name="nodeService" ref="nodeService" /> <!-- use lower case service to enhance performance -->
|
||||||
<property name="freezeService" ref="FreezeService" />
|
<property name="freezeService" ref="FreezeService" />
|
||||||
<property name="recordService" ref="RecordService" />
|
<property name="recordService" ref="RecordService" />
|
||||||
<property name="filePlanService" ref="FilePlanService" />
|
<property name="filePlanService" ref="FilePlanService" />
|
||||||
|
@@ -1214,7 +1214,7 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
|
|||||||
*/
|
*/
|
||||||
public List<AssociationRef> getCustomReferencesTo(NodeRef node)
|
public List<AssociationRef> getCustomReferencesTo(NodeRef node)
|
||||||
{
|
{
|
||||||
return nodeService.getSourceAssocs(node, RegexQNamePattern.MATCH_ALL);
|
return nodeService.getSourceAssocs(node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -213,10 +213,6 @@ public class RMSecurityCommon implements ApplicationContextAware
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the file plan for the node
|
|
||||||
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
|
|
||||||
|
|
||||||
|
|
||||||
if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED)
|
if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED)
|
||||||
{
|
{
|
||||||
// log message
|
// log message
|
||||||
@@ -229,7 +225,9 @@ public class RMSecurityCommon implements ApplicationContextAware
|
|||||||
|
|
||||||
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED);
|
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the file plan for the node
|
||||||
|
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
|
||||||
if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED)
|
if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED)
|
||||||
{
|
{
|
||||||
// log capability details
|
// log capability details
|
||||||
|
@@ -745,7 +745,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
private NodeRef getNextDispositionActionNodeRef(NodeRef nodeRef)
|
private NodeRef getNextDispositionActionNodeRef(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
NodeRef result = null;
|
NodeRef result = null;
|
||||||
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL);
|
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION, 1, true);
|
||||||
if (assocs.size() != 0)
|
if (assocs.size() != 0)
|
||||||
{
|
{
|
||||||
result = assocs.get(0).getChildRef();
|
result = assocs.get(0).getChildRef();
|
||||||
@@ -838,7 +838,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
NodeRef currentDispositionAction = null;
|
NodeRef currentDispositionAction = null;
|
||||||
if (nodeService.hasAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE))
|
if (nodeService.hasAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE))
|
||||||
{
|
{
|
||||||
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL);
|
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION);
|
||||||
if (assocs.size() > 0)
|
if (assocs.size() > 0)
|
||||||
{
|
{
|
||||||
currentDispositionAction = assocs.get(0).getChildRef();
|
currentDispositionAction = assocs.get(0).getChildRef();
|
||||||
|
@@ -186,12 +186,22 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
|
|||||||
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
|
try
|
||||||
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
{
|
||||||
logger.debug("Processed action: " + dispAction + "on" + parent);
|
// execute disposition action
|
||||||
|
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Processed action: " + dispAction + "on" + parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (AlfrescoRuntimeException exception)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -710,17 +710,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isDeclared(NodeRef record)
|
|
||||||
{
|
|
||||||
ParameterCheck.mandatory("record", record);
|
|
||||||
|
|
||||||
return nodeService.hasAspect(record, ASPECT_DECLARED_RECORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
|
@@ -86,7 +86,7 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
|
|||||||
{
|
{
|
||||||
if (nodeService == null)
|
if (nodeService == null)
|
||||||
{
|
{
|
||||||
nodeService = (NodeService)applicationContext.getBean("nodeService");
|
nodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
||||||
}
|
}
|
||||||
return nodeService;
|
return nodeService;
|
||||||
}
|
}
|
||||||
|
@@ -52,6 +52,9 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
|
|
||||||
/** Application context */
|
/** Application context */
|
||||||
protected ApplicationContext applicationContext;
|
protected ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
/** internal node service */
|
||||||
|
private NodeService internalNodeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||||
@@ -77,6 +80,21 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
{
|
{
|
||||||
this.dictionaryService = dictionaryService;
|
this.dictionaryService = dictionaryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to get internal node service.
|
||||||
|
* <p>
|
||||||
|
* Used for performance reasons.
|
||||||
|
*/
|
||||||
|
private NodeService getInternalNodeService()
|
||||||
|
{
|
||||||
|
if (internalNodeService == null)
|
||||||
|
{
|
||||||
|
internalNodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
||||||
|
}
|
||||||
|
|
||||||
|
return internalNodeService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the file plan component kind from the given node reference
|
* Gets the file plan component kind from the given node reference
|
||||||
@@ -196,12 +214,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
public boolean isFilePlanComponent(NodeRef nodeRef)
|
public boolean isFilePlanComponent(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
if (getInternalNodeService().exists(nodeRef) &&
|
||||||
// use the internal node service to prevent redirection of security checking.
|
getInternalNodeService().hasAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT))
|
||||||
NodeService myNodeService = (NodeService)applicationContext.getBean("nodeService");
|
|
||||||
|
|
||||||
if (myNodeService.exists(nodeRef) &&
|
|
||||||
myNodeService.hasAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT))
|
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@@ -264,7 +278,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
{
|
{
|
||||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
|
||||||
return nodeService.hasAspect(nodeRef, ASPECT_RECORD);
|
return getInternalNodeService().hasAspect(nodeRef, ASPECT_RECORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,7 +294,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
|
||||||
boolean isHold = false;
|
boolean isHold = false;
|
||||||
if (nodeService.exists(nodeRef) && instanceOf(nodeRef, TYPE_HOLD))
|
if (getInternalNodeService().exists(nodeRef) &&
|
||||||
|
instanceOf(nodeRef, TYPE_HOLD))
|
||||||
{
|
{
|
||||||
isHold = true;
|
isHold = true;
|
||||||
}
|
}
|
||||||
@@ -298,6 +313,18 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
|
|
||||||
return instanceOf(nodeRef, TYPE_TRANSFER);
|
return instanceOf(nodeRef, TYPE_TRANSFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether a record is complete or not.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public boolean isDeclared(NodeRef record)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("record", record);
|
||||||
|
|
||||||
|
return getInternalNodeService().hasAspect(record, ASPECT_DECLARED_RECORD);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the file plan that a given file plan component resides within.
|
* Gets the file plan that a given file plan component resides within.
|
||||||
@@ -309,35 +336,23 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
{
|
{
|
||||||
NodeRef result = null;
|
NodeRef result = null;
|
||||||
if (nodeRef != null)
|
if (nodeRef != null)
|
||||||
{
|
{
|
||||||
RunAsWork<NodeRef> runAsWork = new RunAsWork<NodeRef>()
|
result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF);
|
||||||
|
if (result == null)
|
||||||
{
|
{
|
||||||
@Override
|
if (instanceOf(nodeRef, TYPE_FILE_PLAN))
|
||||||
public NodeRef doWork()
|
|
||||||
{
|
{
|
||||||
NodeRef result = (NodeRef)nodeService.getProperty(nodeRef, PROP_ROOT_NODEREF);
|
result = nodeRef;
|
||||||
if (result == null)
|
|
||||||
{
|
|
||||||
if (instanceOf(nodeRef, TYPE_FILE_PLAN))
|
|
||||||
{
|
|
||||||
result = nodeRef;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef);
|
|
||||||
if (parentAssocRef != null)
|
|
||||||
{
|
|
||||||
result = getFilePlan(parentAssocRef.getParentRef());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
};
|
{
|
||||||
|
ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef);
|
||||||
result = AuthenticationUtil.runAsSystem(runAsWork);
|
if (parentAssocRef != null)
|
||||||
|
{
|
||||||
|
result = getFilePlan(parentAssocRef.getParentRef());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -352,15 +367,9 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
|
|||||||
protected boolean instanceOf(NodeRef nodeRef, QName ofClassName)
|
protected boolean instanceOf(NodeRef nodeRef, QName ofClassName)
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
ParameterCheck.mandatory("ofClassName", ofClassName);
|
ParameterCheck.mandatory("ofClassName", ofClassName);
|
||||||
boolean result = false;
|
QName className = getInternalNodeService().getType(nodeRef);
|
||||||
if (nodeService.exists(nodeRef) &&
|
return instanceOf(className, ofClassName);
|
||||||
(ofClassName.equals(nodeService.getType(nodeRef)) ||
|
|
||||||
dictionaryService.isSubClass(nodeService.getType(nodeRef), ofClassName)))
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -275,7 +275,8 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
|
|||||||
@Test (expected=AlfrescoRuntimeException.class)
|
@Test (expected=AlfrescoRuntimeException.class)
|
||||||
public void addToHoldNotARecordFolderOrRecord()
|
public void addToHoldNotARecordFolderOrRecord()
|
||||||
{
|
{
|
||||||
holdService.addToHold(hold, filePlanComponent);
|
NodeRef anotherThing = generateNodeRef(TYPE_RECORD_CATEGORY);
|
||||||
|
holdService.addToHold(hold, anotherThing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@@ -121,7 +121,7 @@ public class BaseUnitTest implements RecordsManagementModel
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
// setup application context
|
// setup application context
|
||||||
doReturn(mockedNodeService).when(mockedApplicationContext).getBean("nodeService");
|
doReturn(mockedNodeService).when(mockedApplicationContext).getBean("dbNodeService");
|
||||||
|
|
||||||
// setup retrying transaction helper
|
// setup retrying transaction helper
|
||||||
Answer<Object> doInTransactionAnswer = new Answer<Object>()
|
Answer<Object> doInTransactionAnswer = new Answer<Object>()
|
||||||
|
Reference in New Issue
Block a user