diff --git a/.gitignore b/.gitignore
index 4b9784e791..9c15326934 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,4 +35,4 @@ test-output
# /rm-enterprise/rm-automation-enterprise/
/rm-enterprise/rm-automation-enterprise/l10n
-/rm-enterprise/rm-automation-enterprise/root
+/rm-enterprise/rm-automation-enterprise/root
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
index 50e505c39f..a5b3d722b5 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
@@ -103,7 +103,7 @@
-
+
@@ -195,7 +195,6 @@
-
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index 7ddb3f28b2..d1d575c4d2 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -775,6 +775,7 @@
+
rma:recordCategory
@@ -817,7 +818,6 @@
getCustomConstraintDefinitions(QName modelQName);
+ List getCustomConstraintDefinitions(QName modelQName);
/**
* This method adds a Constraint definition to the custom model.
@@ -374,22 +369,22 @@ public interface RecordsManagementAdminService
* @param title the human-readable title e.g. My foo list
* @param caseSensitive
* @param allowedValues the allowed values list
- * @param matchLogic AND (all values must match), OR (at least one values must match)
+ * @param matchLogic AND (all values must match), OR (at least one values must match)
*/
- void addCustomConstraintDefinition(QName constraintName, String title, boolean caseSensitive, List allowedValues, MatchLogic matchLogic);
+ void addCustomConstraintDefinition(QName constraintName, String title, boolean caseSensitive, List allowedValues, MatchLogic matchLogic);
/**
- * Remove custom constraint definition - if not referenced (by any properties)
+ * Remove custom constraint definition - if not referenced (by any properties)
*
*
- * @param constraintName the name e.g. rmc:foo
+ * @param constraintName the name e.g. rmc:foo
*/
void removeCustomConstraintDefinition(QName constraintName);
/**
- * Update custom constraint definition with new list of values (replaces existing list, if any)
+ * Update custom constraint definition with new list of values (replaces existing list, if any)
*
- * @param constraintName the name e.g. rmc:foo
+ * @param constraintName the name e.g. rmc:foo
* @param newValues
*/
void changeCustomConstraintValues(QName constraintName, List newValues);
@@ -409,7 +404,7 @@ public interface RecordsManagementAdminService
* @return the QName of the property, association definition which matches, or null.
*/
QName getQNameForClientId(String localName);
-
+
/**
* Given a compound id for source and target strings (as used with parent/child
* custom references), this method splits the String and returns an array containing
@@ -419,7 +414,7 @@ public interface RecordsManagementAdminService
* @return a String array, where result[0] == sourceId and result[1] == targetId.
*/
String[] splitSourceTargetId(String sourceTargetId);
-
+
/**
* This method retrieves a compound ID (client-side) for the specified
* sourceId and targetId.
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java
index 8fa2f8b10d..c17b74b822 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java
@@ -24,7 +24,6 @@
* along with Alfresco. If not, see .
* #L%
*/
-
package org.alfresco.module.org_alfresco_module_rm.admin;
import static org.springframework.extensions.surf.util.ParameterCheck.mandatory;
@@ -61,6 +60,7 @@ import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.Constraint;
@@ -73,7 +73,11 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.GUID;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.Ordered;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.surf.util.URLDecoder;
@@ -83,10 +87,14 @@ import org.springframework.extensions.surf.util.URLDecoder;
* @author Neil McErlean, janv
*/
@BehaviourBean
-public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBase implements RecordsManagementAdminService,
- NodeServicePolicies.OnAddAspectPolicy,
- NodeServicePolicies.OnRemoveAspectPolicy,
- NodeServicePolicies.OnCreateNodePolicy
+public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBase
+ implements RecordsManagementAdminService,
+ RecordsManagementCustomModel,
+ NodeServicePolicies.OnAddAspectPolicy,
+ NodeServicePolicies.OnRemoveAspectPolicy,
+ NodeServicePolicies.OnCreateNodePolicy,
+ ApplicationListener,
+ Ordered
{
/** I18N messages*/
private static final String MSG_SERVICE_NOT_INIT = "rm.admin.service-not-init";
@@ -107,14 +115,26 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
/** Relationship service */
private RelationshipService relationshipService;
+
+ /** Transaction service */
+ private TransactionService transactionService;
/** List of types that can be customisable */
private List pendingCustomisableTypes;
private Map customisableTypes;
+
+ /** indicates whether the custom map has been initialised or not */
+ private boolean isCustomMapInit = false;
+
+ /**
+ * @param transactionService transaction service
+ */
+ public void setTransactionService(TransactionService transactionService)
+ {
+ this.transactionService = transactionService;
+ }
/**
- * Sets the relationship instance
- *
* @param relationshipService The relationship service instance
*/
public void setRelationshipService(RelationshipService relationshipService)
@@ -132,6 +152,48 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
return this.relationshipService;
}
+ /**
+ * Indicate that this application content listener must be executed with the lowest
+ * precedence. (ie last)
+ *
+ * @see Ordered#getOrder()
+ */
+ @Override
+ public int getOrder()
+ {
+ return Ordered.LOWEST_PRECEDENCE;
+ }
+
+ /**
+ * Load the custom properties map
+ *
+ * @see ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
+ */
+ @Override
+ public void onApplicationEvent(ContextRefreshedEvent event)
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ // initialise custom properties
+ initCustomMap();
+
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Helper method to indicate whether the custom map is initialised or not.
+ *
+ * @return boolean true if initialised, false otherwise
+ */
+ public boolean isCustomMapInit()
+ {
+ return isCustomMapInit;
+ }
+
/**
* @see org.alfresco.repo.node.NodeServicePolicies.OnAddAspectPolicy#onAddAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
*/
@@ -144,25 +206,25 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
)
public void onAddAspect(final NodeRef nodeRef, final QName aspectTypeQName)
{
- mandatory("nodeRef", nodeRef);
- mandatory("aspectTypeQName", aspectTypeQName);
-
- AuthenticationUtil.runAs(new RunAsWork()
+ if (isCustomMapInit)
{
- @Override
- public Void doWork()
+ AuthenticationUtil.runAs(new RunAsWork()
{
- if (getNodeService().exists(nodeRef) &&
- getDictionaryService().getAllModels().contains(RM_CUSTOM_MODEL) &&
- isCustomisable(aspectTypeQName))
+ @Override
+ public Void doWork()
{
- QName customPropertyAspect = getCustomAspect(aspectTypeQName);
- getNodeService().addAspect(nodeRef, customPropertyAspect, null);
+ if (getNodeService().exists(nodeRef) &&
+ getDictionaryService().getAllModels().contains(RM_CUSTOM_MODEL) &&
+ isCustomisable(aspectTypeQName))
+ {
+ QName customPropertyAspect = getCustomAspect(aspectTypeQName);
+ getNodeService().addAspect(nodeRef, customPropertyAspect, null);
+ }
+
+ return null;
}
-
- return null;
- }
- }, AuthenticationUtil.getSystemUserName());
+ }, AuthenticationUtil.getSystemUserName());
+ }
}
/**
@@ -177,24 +239,24 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
)
public void onRemoveAspect(final NodeRef nodeRef, final QName aspectTypeQName)
{
- mandatory("nodeRef", nodeRef);
- mandatory("aspectTypeQName", aspectTypeQName);
-
- AuthenticationUtil.runAs(new RunAsWork()
+ if (isCustomMapInit)
{
- @Override
- public Void doWork()
+ AuthenticationUtil.runAs(new RunAsWork()
{
- if (getNodeService().exists(nodeRef) &&
- isCustomisable(aspectTypeQName))
+ @Override
+ public Void doWork()
{
- QName customPropertyAspect = getCustomAspect(aspectTypeQName);
- getNodeService().removeAspect(nodeRef, customPropertyAspect);
+ if (getNodeService().exists(nodeRef) &&
+ isCustomisable(aspectTypeQName))
+ {
+ QName customPropertyAspect = getCustomAspect(aspectTypeQName);
+ getNodeService().removeAspect(nodeRef, customPropertyAspect);
+ }
+
+ return null;
}
-
- return null;
- }
- }, AuthenticationUtil.getSystemUserName());
+ }, AuthenticationUtil.getSystemUserName());
+ }
}
/**
@@ -211,49 +273,41 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
)
public void onCreateNode(final ChildAssociationRef childAssocRef)
{
- mandatory("nodeRef", childAssocRef);
-
- AuthenticationUtil.runAs(new RunAsWork()
- {
- @Override
- public Void doWork()
+ if (isCustomMapInit)
+ {
+ AuthenticationUtil.runAs(new RunAsWork()
{
- if (getDictionaryService().getAllModels().contains(RecordsManagementCustomModel.RM_CUSTOM_MODEL))
+ @Override
+ public Void doWork()
{
- NodeRef nodeRef = childAssocRef.getChildRef();
- QName type = getNodeService().getType(nodeRef);
- while (type != null && !ContentModel.TYPE_CMOBJECT.equals(type))
+ if (getDictionaryService().getAllModels().contains(RecordsManagementCustomModel.RM_CUSTOM_MODEL))
{
- if (isCustomisable(type))
+ NodeRef nodeRef = childAssocRef.getChildRef();
+ QName type = getNodeService().getType(nodeRef);
+ while (type != null && !ContentModel.TYPE_CMOBJECT.equals(type))
{
- QName customPropertyAspect = getCustomAspect(type);
- getNodeService().addAspect(nodeRef, customPropertyAspect, null);
- }
-
- TypeDefinition def = getDictionaryService().getType(type);
- if (def != null)
- {
- type = def.getParentName();
- }
- else
- {
- type = null;
+ if (isCustomisable(type))
+ {
+ QName customPropertyAspect = getCustomAspect(type);
+ getNodeService().addAspect(nodeRef, customPropertyAspect, null);
+ }
+
+ TypeDefinition def = getDictionaryService().getType(type);
+ if (def != null)
+ {
+ type = def.getParentName();
+ }
+ else
+ {
+ type = null;
+ }
}
}
+
+ return null;
}
-
- return null;
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementAdminService#initialiseCustomModel()
- */
- public void initialiseCustomModel()
- {
- // Initialise the map
- getCustomisableMap();
+ }, AuthenticationUtil.getSystemUserName());
+ }
}
/**
@@ -338,6 +392,92 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
return result;
}
+
+ /**
+ * Initialise custom type map
+ */
+ private void initCustomMap()
+ {
+ customisableTypes = new HashMap(7);
+ Collection aspects = getDictionaryService().getAspects(RM_CUSTOM_MODEL);
+ for (QName aspect : aspects)
+ {
+ AspectDefinition aspectDef = getDictionaryService().getAspect(aspect);
+ String name = aspectDef.getName().getLocalName();
+ if (name.endsWith("Properties"))
+ {
+ QName type = null;
+ String prefixString = aspectDef.getDescription(getDictionaryService());
+ if (prefixString == null)
+ {
+ // Backward compatibility from previous RM V1.0 custom models
+ if (CompatibilityModel.NAME_CUSTOM_RECORD_PROPERTIES.equals(name))
+ {
+ type = RecordsManagementModel.ASPECT_RECORD;
+ }
+ else if (CompatibilityModel.NAME_CUSTOM_RECORD_FOLDER_PROPERTIES.equals(name))
+ {
+ type = RecordsManagementModel.TYPE_RECORD_FOLDER;
+ }
+ else if (CompatibilityModel.NAME_CUSTOM_RECORD_CATEGORY_PROPERTIES.equals(name))
+ {
+ type = RecordsManagementModel.TYPE_RECORD_CATEGORY;
+ }
+ else if (CompatibilityModel.NAME_CUSTOM_RECORD_SERIES_PROPERTIES.equals(name) &&
+ // Only add the deprecated record series type as customisable if
+ // a v1.0 installation has added custom properties
+ aspectDef.getProperties().size() != 0)
+ {
+ type = CompatibilityModel.TYPE_RECORD_SERIES;
+ }
+ }
+ else
+ {
+ type = QName.createQName(prefixString, getNamespaceService());
+ }
+
+ // Add the customisable type to the map
+ if (type != null)
+ {
+ customisableTypes.put(type, aspect);
+
+ // Remove customisable type from the pending list
+ if (pendingCustomisableTypes != null && pendingCustomisableTypes.contains(type))
+ {
+ pendingCustomisableTypes.remove(type);
+ }
+ }
+ }
+ }
+
+ // Deal with any pending types left over
+ if (pendingCustomisableTypes != null && pendingCustomisableTypes.size() != 0)
+ {
+ NodeRef modelRef = getCustomModelRef(RecordsManagementModel.RM_CUSTOM_URI);
+ M2Model model = readCustomContentModel(modelRef);
+ try
+ {
+ for (QName customisableType : pendingCustomisableTypes)
+ {
+ QName customAspect = getCustomAspectImpl(customisableType);
+
+ // Create the new aspect to hold the custom properties
+ M2Aspect aspect = model.createAspect(customAspect.toPrefixString(getNamespaceService()));
+ aspect.setDescription(customisableType.toPrefixString(getNamespaceService()));
+
+ // Make a record of the customisable type
+ customisableTypes.put(customisableType, customAspect);
+ }
+ }
+ finally
+ {
+ writeCustomContentModel(modelRef, model);
+ }
+ }
+
+ // indicate map is initialised
+ isCustomMapInit = true;
+ }
/**
* Gets a map containing all the customisable types
@@ -346,86 +486,11 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
*/
private Map getCustomisableMap()
{
- if (customisableTypes == null)
- {
- customisableTypes = new HashMap(7);
- Collection aspects = getDictionaryService().getAspects(RM_CUSTOM_MODEL);
- for (QName aspect : aspects)
- {
- AspectDefinition aspectDef = getDictionaryService().getAspect(aspect);
- String name = aspectDef.getName().getLocalName();
- if (name.endsWith("Properties"))
- {
- QName type = null;
- String prefixString = aspectDef.getDescription(getDictionaryService());
- if (prefixString == null)
- {
- // Backward compatibility from previous RM V1.0 custom models
- if (CompatibilityModel.NAME_CUSTOM_RECORD_PROPERTIES.equals(name))
- {
- type = RecordsManagementModel.ASPECT_RECORD;
- }
- else if (CompatibilityModel.NAME_CUSTOM_RECORD_FOLDER_PROPERTIES.equals(name))
- {
- type = RecordsManagementModel.TYPE_RECORD_FOLDER;
- }
- else if (CompatibilityModel.NAME_CUSTOM_RECORD_CATEGORY_PROPERTIES.equals(name))
- {
- type = RecordsManagementModel.TYPE_RECORD_CATEGORY;
- }
- else if (CompatibilityModel.NAME_CUSTOM_RECORD_SERIES_PROPERTIES.equals(name) &&
- // Only add the deprecated record series type as customisable if
- // a v1.0 installation has added custom properties
- aspectDef.getProperties().size() != 0)
- {
- type = CompatibilityModel.TYPE_RECORD_SERIES;
- }
- }
- else
- {
- type = QName.createQName(prefixString, getNamespaceService());
- }
-
- // Add the customisable type to the map
- if (type != null)
- {
- customisableTypes.put(type, aspect);
-
- // Remove customisable type from the pending list
- if (pendingCustomisableTypes != null && pendingCustomisableTypes.contains(type))
- {
- pendingCustomisableTypes.remove(type);
- }
- }
- }
- }
-
- // Deal with any pending types left over
- if (pendingCustomisableTypes != null && pendingCustomisableTypes.size() != 0)
- {
- NodeRef modelRef = getCustomModelRef(RecordsManagementModel.RM_CUSTOM_URI);
- M2Model model = readCustomContentModel(modelRef);
- try
- {
- for (QName customisableType : pendingCustomisableTypes)
- {
- QName customAspect = getCustomAspectImpl(customisableType);
-
- // Create the new aspect to hold the custom properties
- M2Aspect aspect = model.createAspect(customAspect.toPrefixString(getNamespaceService()));
- aspect.setDescription(customisableType.toPrefixString(getNamespaceService()));
-
- // Make a record of the customisable type
- customisableTypes.put(customisableType, customAspect);
- }
- }
- finally
- {
- writeCustomContentModel(modelRef, model);
- }
- }
- }
- return customisableTypes;
+ if (customisableTypes == null)
+ {
+ throw AlfrescoRuntimeException.create("Customisable map has not been initialised correctly.");
+ }
+ return customisableTypes;
}
/**
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/bootstrap/RecordsManagementBootstrap.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/bootstrap/RecordsManagementBootstrap.java
index f78b5a15bd..2c59e2f155 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/bootstrap/RecordsManagementBootstrap.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/bootstrap/RecordsManagementBootstrap.java
@@ -28,7 +28,6 @@
package org.alfresco.module.org_alfresco_module_rm.bootstrap;
import org.alfresco.module.org_alfresco_module_rm.action.impl.SplitEmailAction;
-import org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminService;
import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigService;
import org.alfresco.module.org_alfresco_module_rm.email.CustomEmailMappingService;
import org.alfresco.repo.action.parameter.NodeParameterSuggesterBootstrap;
@@ -50,7 +49,6 @@ public class RecordsManagementBootstrap extends AbstractLifecycleBean
private TransactionService transactionService;
private RMCaveatConfigService caveatConfigService;
private CustomEmailMappingService customEmailMappingService;
- private RecordsManagementAdminService adminService;
private NodeParameterSuggesterBootstrap suggesterBootstrap;
public NodeParameterSuggesterBootstrap getSuggesterBootstrap()
@@ -78,11 +76,6 @@ public class RecordsManagementBootstrap extends AbstractLifecycleBean
this.customEmailMappingService = customEmailMappingService;
}
- public void setRecordsManagementAdminService(RecordsManagementAdminService adminService)
- {
- this.adminService = adminService;
- }
-
public CustomEmailMappingService getCustomEmailMappingService()
{
return customEmailMappingService;
@@ -102,9 +95,6 @@ public class RecordsManagementBootstrap extends AbstractLifecycleBean
{
// initialise caveat config
caveatConfigService.init();
-
- // Initialise the custom model
- adminService.initialiseCustomModel();
// Initialize the suggester after the model
// in case it contains namespaces from custom models
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/rm3314/RM3314Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/rm3314/RM3314Test.java
new file mode 100644
index 0000000000..7bc0a982bf
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/rm3314/RM3314Test.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2005-2016 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue.rm3314;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+
+/**
+ * Test for https://issues.alfresco.com/jira/browse/RM-3114
+ *
+ * @author Roy Wetherall
+ * @since 2.2.1.5
+ */
+public class RM3314Test extends BaseRMTestCase
+{
+ /** registry to record callback from test beans "test.rm3114.1" and "test.rm3114.2" */
+ public static Map callback = new HashMap(2);
+
+ /**
+ * Given that the custom model hasn't been initialised
+ * When an aspect is added
+ * Then nothing happens
+ *
+ * Given that the custom model has been initialised
+ * When an aspect is added
+ * Then something happens
+ */
+ public void testListenersExecutedInTheCorrectOrder()
+ {
+ /**
+ * The related test beans will call back into the callback map showing
+ * whether at the end of their execution whether the custom model has been
+ * initialised or not. Given the order in which these test beans are executed
+ * on spring context load, we would expect that .1 executes with the custom
+ * map unloaded, and the .2 with it loaded.
+ */
+
+ assertFalse(callback.isEmpty());
+ assertFalse(callback.get("test.rm3314.1"));
+ assertTrue(callback.get("test.rm3314.2"));
+ }
+}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/rm3314/RM3314TestListener.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/rm3314/RM3314TestListener.java
new file mode 100644
index 0000000000..d162d0fe95
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/rm3314/RM3314TestListener.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue.rm3314;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminServiceImpl;
+import org.alfresco.repo.model.Repository;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.Ordered;
+import org.springframework.jdbc.BadSqlGrammarException;
+
+/**
+ * Simple bean used to test RM-3314
+ *
+ * @author rwetherall
+ * @since 2.2.1.5
+ */
+public class RM3314TestListener implements ApplicationListener,
+ Ordered,
+ BeanNameAware
+{
+ private RecordsManagementAdminServiceImpl recordsManagementAdminService;
+ private NodeService nodeService;
+ private FileFolderService fileFolderService;
+ private Repository repository;
+
+ private String name;
+ private int order = Ordered.LOWEST_PRECEDENCE;
+
+ public void setRecordsManagementAdminService(RecordsManagementAdminServiceImpl recordsManagementAdminService)
+ {
+ this.recordsManagementAdminService = recordsManagementAdminService;
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public void setFileFolderService(FileFolderService fileFolderService)
+ {
+ this.fileFolderService = fileFolderService;
+ }
+
+ public void setRepository(Repository repository)
+ {
+ this.repository = repository;
+ }
+
+ @Override
+ public void setBeanName(String name)
+ {
+ this.name = name;
+ }
+
+ public void setOrder(int order)
+ {
+ this.order = order;
+ }
+
+ @Override
+ public void onApplicationEvent(ContextRefreshedEvent event)
+ {
+ // call back to show whether the custom map is initialised or not
+ RM3314Test.callback.put(name, recordsManagementAdminService.isCustomMapInit());
+
+ // Do some work on a node to show that reguardless of whether the custom map is
+ // init or not, things still work.
+ // Note: using public services to ensure new transaction for each service call
+ AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ public Void doWork() throws Exception
+ {
+ try
+ {
+ // create node
+ NodeRef folder = fileFolderService.create(
+ repository.getCompanyHome(),
+ name,
+ ContentModel.TYPE_FOLDER).getNodeRef();
+ try
+ {
+ // add aspect
+ nodeService.addAspect(folder, ContentModel.ASPECT_CLASSIFIABLE, null);
+
+ // remove aspect
+ nodeService.removeAspect(folder, ContentModel.ASPECT_CLASSIFIABLE);
+ }
+ finally
+ {
+ // delete node
+ nodeService.deleteNode(folder);
+ }
+ }
+ catch (BadSqlGrammarException e)
+ {
+ // ignore and carry on
+ }
+
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public int getOrder()
+ {
+ return order;
+ }
+}
diff --git a/rm-community/rm-community-repo/test/resources/test-context.xml b/rm-community/rm-community-repo/test/resources/test-context.xml
index f00d3e56b6..e79bdda973 100644
--- a/rm-community/rm-community-repo/test/resources/test-context.xml
+++ b/rm-community/rm-community-repo/test/resources/test-context.xml
@@ -245,5 +245,26 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file