diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml
new file mode 100644
index 0000000000..63ccdb75e8
--- /dev/null
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties
index 6830ad62fe..a8d3e2c6b3 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties
@@ -1,3 +1,3 @@
# RM Schema number
-version.rm.schema=3300
+version.rm.schema=3500
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java
new file mode 100644
index 0000000000..0b620d07df
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java
@@ -0,0 +1,127 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.patch.v35;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
+import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
+import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch;
+import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+
+/**
+ * Patch to create new hold child association to link the record to the hold
+ *
+ * See: https://alfresco.atlassian.net/browse/APPS-659
+ *
+ *
+ * @since 3.5
+ */
+public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
+{
+ /**
+ * File plan service interface
+ */
+ private FilePlanService filePlanService;
+
+ /**
+ * Hold service interface.
+ */
+ private HoldService holdService;
+
+ /**
+ * Interface for public and internal node and store operations.
+ */
+ private NodeService nodeService;
+
+ private BehaviourFilter behaviourFilter;
+
+ /**
+ * Setter for fileplanservice
+ * @param filePlanService File plan service interface
+ */
+ public void setFilePlanService(FilePlanService filePlanService)
+ {
+ this.filePlanService = filePlanService;
+ }
+
+ /**
+ * Setter for hold service
+ * @param holdService Hold service interface.
+ */
+ public void setHoldService(HoldService holdService)
+ {
+ this.holdService = holdService;
+ }
+
+ /**
+ * Setter for node service
+ * @param nodeService Interface for public and internal node and store operations.
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public BehaviourFilter getBehaviourFilter()
+ {
+ return behaviourFilter;
+ }
+
+ public void setBehaviourFilter(BehaviourFilter behaviourFilter)
+ {
+ this.behaviourFilter = behaviourFilter;
+ }
+
+ @Override
+ public void applyInternal()
+ {
+ behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
+ behaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
+ try
+ {
+ for (NodeRef filePlan : filePlanService.getFilePlans())
+ {
+ for (NodeRef hold : holdService.getHolds(filePlan))
+ {
+ for (ChildAssociationRef ref : nodeService.getChildAssocs(hold))
+ {
+ holdService.removeFromHold(hold, ref.getChildRef());
+ holdService.addToHold(hold, ref.getChildRef());
+ }
+ }
+ }
+ }
+ finally
+ {
+ behaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
+ behaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
+ }
+ }
+}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java
new file mode 100644
index 0000000000..01b04de73d
--- /dev/null
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java
@@ -0,0 +1,158 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.patch.v35;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyMap;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
+import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
+import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * RM V3.5 Create new hold child association to link the record to the hold
+ *
+ * @since 3.5
+ */
+public class RMv35HoldNewChildAssocPatchUnitTest
+{
+ @Mock
+ private FilePlanService mockFilePlanService;
+
+ @Mock
+ private HoldService mockHoldService;
+
+ @Mock
+ private NodeService mockNodeService;
+
+ @Mock
+ private BehaviourFilter mockBehaviourFilter;
+
+ @InjectMocks
+ private RMv35HoldNewChildAssocPatch patch;
+
+ private NodeRef filePlanRef, holdRef, heldItemRef;
+ private Set fileplans;
+ private List holds;
+
+ @Mock
+ private ChildAssociationRef childAssociationRef;
+
+ private List childAssocs;
+
+ @Before
+ public void setUp()
+ {
+ MockitoAnnotations.initMocks(this);
+ filePlanRef = new NodeRef("workspace://SpacesStore/filePlan");
+ holdRef = new NodeRef("workspace://SpacesStore/hold");
+ heldItemRef = new NodeRef("workspace://SpacesStore/heldItem");
+ fileplans = new HashSet<>();
+ fileplans.add(filePlanRef);
+ holds = new ArrayList<>();
+ holds.add(holdRef);
+ childAssocs = new ArrayList<>();
+ childAssocs.add(childAssociationRef);
+ }
+
+ /**
+ * Test held items are removed from a hold and re-add to make sure the association is correct
+ */
+ @Test
+ public void testAHoldIsRemovedAndReplacedDuringUpgrade()
+ {
+ when(mockFilePlanService.getFilePlans()).thenReturn(fileplans);
+ when(mockHoldService.getHolds(filePlanRef)).thenReturn(holds);
+ when(childAssociationRef.getChildRef()).thenReturn(heldItemRef);
+ when(mockNodeService.getChildAssocs(holdRef)).thenReturn(childAssocs);
+ patch.applyInternal();
+ verify(mockHoldService, times(1)).removeFromHold(holdRef, heldItemRef);
+ verify(mockHoldService, times(1)).addToHold(holdRef, heldItemRef);
+ }
+
+ @Test
+ public void patchRunWithSuccessWhenNoHoldChilds()
+ {
+ List holdList = new ArrayList<>();
+ holdList.add(holdRef);
+ when(childAssociationRef.getChildRef()).thenReturn(heldItemRef);
+ when(mockNodeService.getChildAssocs(holdRef)).thenReturn(new ArrayList<>());
+ patch.applyInternal();
+
+ verify(mockHoldService, times(0)).removeFromHold(holdRef, heldItemRef);
+ verify(mockHoldService, times(0)).addToHold(holdRef, heldItemRef);
+
+ }
+
+ @Test
+ public void patchRunWithSuccessWhenNoHolds()
+ {
+ //no holds
+ List holdList = new ArrayList<>();
+ when(mockFilePlanService.getFilePlans()).thenReturn(fileplans);
+ when(mockHoldService.getHolds(filePlanRef)).thenReturn(holdList);
+ patch.applyInternal();
+
+ verify(mockHoldService, times(0)).removeFromHold(holdRef, heldItemRef);
+ verify(mockHoldService, times(0)).addToHold(holdRef, heldItemRef);
+ }
+
+ @Test
+ public void patchRunWithSuccessWhenNoFilePlan()
+ {
+ // given
+ doReturn(Collections.EMPTY_SET).when(mockFilePlanService).getFilePlans();
+
+ // when
+ patch.applyInternal();
+
+ // then
+ verifyZeroInteractions(mockHoldService);
+ verify(mockNodeService, times(0)).addAspect(any(NodeRef.class), any(QName.class), anyMap());
+ }
+}