diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java
index 90c1715f9e8c..9a72f0828e22 100644
--- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java
+++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java
@@ -38,6 +38,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.function.LongSupplier;
@@ -47,6 +48,7 @@
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.SoftDeletableObject;
 import org.hisp.dhis.common.SortDirection;
+import org.hisp.dhis.common.UID;
 import org.hisp.dhis.common.hibernate.SoftDeleteHibernateObjectStore;
 import org.hisp.dhis.program.Enrollment;
 import org.hisp.dhis.program.Event;
@@ -88,6 +90,49 @@ public HibernateRelationshipStore(
     super(entityManager, jdbcTemplate, publisher, Relationship.class, aclService, true);
   }
 
+  @Override
+  public Optional<TrackedEntity> findTrackedEntity(UID trackedEntity) {
+    @Language("hql")
+    String hql =
+        """
+                from TrackedEntity te
+                where te.uid = :trackedEntity
+                """;
+    List<TrackedEntity> trackedEntities =
+        getQuery(hql, TrackedEntity.class)
+            .setParameter("trackedEntity", trackedEntity.getValue())
+            .getResultList();
+    return trackedEntities.stream().findFirst();
+  }
+
+  @Override
+  public Optional<Enrollment> findEnrollment(UID enrollment) {
+    @Language("hql")
+    String hql =
+        """
+                from Enrollment e
+                where e.uid = :enrollment
+                """;
+    List<Enrollment> enrollments =
+        getQuery(hql, Enrollment.class)
+            .setParameter("enrollment", enrollment.getValue())
+            .getResultList();
+    return enrollments.stream().findFirst();
+  }
+
+  @Override
+  public Optional<Event> findEvent(UID event) {
+    @Language("hql")
+    String hql =
+        """
+                from Event e
+                where e.uid = :event
+                """;
+    List<Event> events =
+        getQuery(hql, Event.class).setParameter("event", event.getValue()).getResultList();
+    return events.stream().findFirst();
+  }
+
   @Override
   public List<Relationship> getByTrackedEntity(
       TrackedEntity trackedEntity, RelationshipQueryParams queryParams) {
diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java
index 6b558714052b..6a7e9ae9fe07 100644
--- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java
+++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java
@@ -30,12 +30,14 @@
 import javax.annotation.Nonnull;
 import lombok.RequiredArgsConstructor;
 import org.hisp.dhis.common.IdentifiableObject;
-import org.hisp.dhis.feedback.BadRequestException;
+import org.hisp.dhis.common.UID;
 import org.hisp.dhis.feedback.ForbiddenException;
 import org.hisp.dhis.feedback.NotFoundException;
-import org.hisp.dhis.tracker.export.enrollment.EnrollmentService;
-import org.hisp.dhis.tracker.export.event.EventService;
-import org.hisp.dhis.tracker.export.trackedentity.TrackedEntityService;
+import org.hisp.dhis.program.Enrollment;
+import org.hisp.dhis.program.Event;
+import org.hisp.dhis.trackedentity.TrackedEntity;
+import org.hisp.dhis.tracker.acl.TrackerAccessManager;
+import org.hisp.dhis.user.CurrentUserUtil;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -47,19 +49,18 @@
 @RequiredArgsConstructor
 class RelationshipOperationParamsMapper {
 
-  private final TrackedEntityService trackedEntityService;
-  private final EnrollmentService enrollmentService;
-  private final EventService eventService;
+  private final RelationshipStore relationshipStore;
+  private final TrackerAccessManager trackerAccessManager;
 
   @Transactional(readOnly = true)
   public RelationshipQueryParams map(@Nonnull RelationshipOperationParams params)
-      throws NotFoundException, ForbiddenException, BadRequestException {
+      throws NotFoundException, ForbiddenException {
 
     IdentifiableObject entity =
         switch (params.getType()) {
-          case TRACKED_ENTITY -> trackedEntityService.getTrackedEntity(params.getIdentifier());
-          case ENROLLMENT -> enrollmentService.getEnrollment(params.getIdentifier());
-          case EVENT -> eventService.getEvent(params.getIdentifier());
+          case TRACKED_ENTITY -> getTrackedEntity(params.getIdentifier());
+          case ENROLLMENT -> getEnrollment(params.getIdentifier());
+          case EVENT -> getEvent(params.getIdentifier());
           case RELATIONSHIP -> throw new IllegalArgumentException("Unsupported type");
         };
 
@@ -69,4 +70,44 @@ public RelationshipQueryParams map(@Nonnull RelationshipOperationParams params)
         .includeDeleted(params.isIncludeDeleted())
         .build();
   }
+
+  private TrackedEntity getTrackedEntity(UID trackedEntityUid)
+      throws NotFoundException, ForbiddenException {
+    TrackedEntity trackedEntity =
+        relationshipStore
+            .findTrackedEntity(trackedEntityUid)
+            .orElseThrow(() -> new NotFoundException(TrackedEntity.class, trackedEntityUid));
+    if (!trackerAccessManager
+        .canRead(CurrentUserUtil.getCurrentUserDetails(), trackedEntity)
+        .isEmpty()) {
+      throw new ForbiddenException(TrackedEntity.class, trackedEntityUid);
+    }
+    return trackedEntity;
+  }
+
+  private Enrollment getEnrollment(UID enrollmentUid) throws NotFoundException, ForbiddenException {
+    Enrollment enrollment =
+        relationshipStore
+            .findEnrollment(enrollmentUid)
+            .orElseThrow(() -> new NotFoundException(Enrollment.class, enrollmentUid));
+    if (!trackerAccessManager
+        .canRead(CurrentUserUtil.getCurrentUserDetails(), enrollment, false)
+        .isEmpty()) {
+      throw new ForbiddenException(Enrollment.class, enrollmentUid);
+    }
+    return enrollment;
+  }
+
+  private Event getEvent(UID eventUid) throws NotFoundException, ForbiddenException {
+    Event event =
+        relationshipStore
+            .findEvent(eventUid)
+            .orElseThrow(() -> new NotFoundException(Event.class, eventUid));
+    if (!trackerAccessManager
+        .canRead(CurrentUserUtil.getCurrentUserDetails(), event, false)
+        .isEmpty()) {
+      throw new ForbiddenException(Event.class, eventUid);
+    }
+    return event;
+  }
 }
diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java
index 0bc854263f50..aad60640c66b 100644
--- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java
+++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java
@@ -28,8 +28,10 @@
 package org.hisp.dhis.tracker.export.relationship;
 
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import org.hisp.dhis.common.IdentifiableObjectStore;
+import org.hisp.dhis.common.UID;
 import org.hisp.dhis.program.Enrollment;
 import org.hisp.dhis.program.Event;
 import org.hisp.dhis.relationship.Relationship;
@@ -40,6 +42,12 @@
 public interface RelationshipStore extends IdentifiableObjectStore<Relationship> {
   String ID = RelationshipStore.class.getName();
 
+  Optional<TrackedEntity> findTrackedEntity(UID trackedEntity);
+
+  Optional<Enrollment> findEnrollment(UID enrollment);
+
+  Optional<Event> findEvent(UID event);
+
   List<Relationship> getByTrackedEntity(
       TrackedEntity trackedEntity, RelationshipQueryParams queryParams);
 
diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java
index f747fcb23ea2..58729472fa97 100644
--- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java
+++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java
@@ -33,12 +33,13 @@
 import static org.hisp.dhis.tracker.TrackerType.TRACKED_ENTITY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.when;
 
 import java.util.List;
+import java.util.Optional;
 import org.hisp.dhis.common.SortDirection;
 import org.hisp.dhis.common.UID;
-import org.hisp.dhis.feedback.BadRequestException;
 import org.hisp.dhis.feedback.ForbiddenException;
 import org.hisp.dhis.feedback.NotFoundException;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -50,9 +51,8 @@
 import org.hisp.dhis.trackedentity.TrackedEntity;
 import org.hisp.dhis.tracker.acl.TrackerAccessManager;
 import org.hisp.dhis.tracker.export.Order;
-import org.hisp.dhis.tracker.export.enrollment.EnrollmentService;
-import org.hisp.dhis.tracker.export.event.EventService;
-import org.hisp.dhis.tracker.export.trackedentity.TrackedEntityService;
+import org.hisp.dhis.user.SystemUser;
+import org.hisp.dhis.user.UserDetails;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -69,13 +69,9 @@ class RelationshipOperationParamsMapperTest extends TestBase {
 
   private static final UID EV_UID = UID.of("TvjwTPToKHO");
 
-  @Mock private TrackedEntityService trackedEntityService;
+  @Mock private RelationshipStore relationshipStore;
 
-  @Mock private EnrollmentService enrollmentService;
-
-  @Mock private EventService eventService;
-
-  @Mock private TrackerAccessManager accessManager;
+  @Mock private TrackerAccessManager trackerAccessManager;
 
   @InjectMocks private RelationshipOperationParamsMapper mapper;
 
@@ -85,6 +81,8 @@ class RelationshipOperationParamsMapperTest extends TestBase {
 
   private Event event;
 
+  private UserDetails user;
+
   @BeforeEach
   public void setUp() {
     OrganisationUnit organisationUnit = createOrganisationUnit('A');
@@ -97,12 +95,14 @@ public void setUp() {
     enrollment.setUid(EN_UID.getValue());
     event = createEvent(programStage, enrollment, organisationUnit);
     event.setUid(EV_UID.getValue());
+    user = new SystemUser();
+    injectSecurityContextNoSettings(user);
   }
 
   @Test
   void shouldMapTrackedEntityWhenATrackedEntityIsPassed()
-      throws NotFoundException, ForbiddenException, BadRequestException {
-    when(trackedEntityService.getTrackedEntity(TE_UID)).thenReturn(trackedEntity);
+      throws NotFoundException, ForbiddenException {
+    when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity));
     RelationshipOperationParams params =
         RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build();
 
@@ -113,9 +113,27 @@ void shouldMapTrackedEntityWhenATrackedEntityIsPassed()
   }
 
   @Test
-  void shouldMapEnrollmentWhenAEnrollmentIsPassed()
-      throws NotFoundException, ForbiddenException, BadRequestException {
-    when(enrollmentService.getEnrollment(EN_UID)).thenReturn(enrollment);
+  void shouldThrowNotFoundExceptionWhenATrackedEntityIsNotPresent() {
+    when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.empty());
+    RelationshipOperationParams params =
+        RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build();
+
+    assertThrows(NotFoundException.class, () -> mapper.map(params));
+  }
+
+  @Test
+  void shouldThrowForbiddenExceptionWhenATrackedEntityIsNotAccessible() {
+    when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity));
+    when(trackerAccessManager.canRead(user, trackedEntity)).thenReturn(List.of("error"));
+    RelationshipOperationParams params =
+        RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build();
+
+    assertThrows(ForbiddenException.class, () -> mapper.map(params));
+  }
+
+  @Test
+  void shouldMapEnrollmentWhenAEnrollmentIsPassed() throws NotFoundException, ForbiddenException {
+    when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.of(enrollment));
     RelationshipOperationParams params =
         RelationshipOperationParams.builder().type(ENROLLMENT).identifier(EN_UID).build();
 
@@ -126,9 +144,27 @@ void shouldMapEnrollmentWhenAEnrollmentIsPassed()
   }
 
   @Test
-  void shouldMapEventWhenAEventIsPassed()
-      throws NotFoundException, ForbiddenException, BadRequestException {
-    when(eventService.getEvent(EV_UID)).thenReturn(event);
+  void shouldThrowNotFoundExceptionWhenAnEnrollmentIsNotPresent() {
+    when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.empty());
+    RelationshipOperationParams params =
+        RelationshipOperationParams.builder().type(ENROLLMENT).identifier(EN_UID).build();
+
+    assertThrows(NotFoundException.class, () -> mapper.map(params));
+  }
+
+  @Test
+  void shouldThrowForbiddenExceptionWhenAnEnrollmentIsNotAccessible() {
+    when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.of(enrollment));
+    when(trackerAccessManager.canRead(user, enrollment, false)).thenReturn(List.of("error"));
+    RelationshipOperationParams params =
+        RelationshipOperationParams.builder().type(ENROLLMENT).identifier(EN_UID).build();
+
+    assertThrows(ForbiddenException.class, () -> mapper.map(params));
+  }
+
+  @Test
+  void shouldMapEventWhenAEventIsPassed() throws NotFoundException, ForbiddenException {
+    when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.of(event));
     RelationshipOperationParams params =
         RelationshipOperationParams.builder().type(EVENT).identifier(EV_UID).build();
 
@@ -139,9 +175,27 @@ void shouldMapEventWhenAEventIsPassed()
   }
 
   @Test
-  void shouldMapOrderInGivenOrder()
-      throws ForbiddenException, NotFoundException, BadRequestException {
-    when(trackedEntityService.getTrackedEntity(TE_UID)).thenReturn(trackedEntity);
+  void shouldThrowNotFoundExceptionWhenAnEventIsNotPresent() {
+    when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.empty());
+    RelationshipOperationParams params =
+        RelationshipOperationParams.builder().type(EVENT).identifier(EV_UID).build();
+
+    assertThrows(NotFoundException.class, () -> mapper.map(params));
+  }
+
+  @Test
+  void shouldThrowForbiddenExceptionWhenAnEventIsNotAccessible() {
+    when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.of(event));
+    when(trackerAccessManager.canRead(user, event, false)).thenReturn(List.of("error"));
+    RelationshipOperationParams params =
+        RelationshipOperationParams.builder().type(EVENT).identifier(EV_UID).build();
+
+    assertThrows(ForbiddenException.class, () -> mapper.map(params));
+  }
+
+  @Test
+  void shouldMapOrderInGivenOrder() throws ForbiddenException, NotFoundException {
+    when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity));
 
     RelationshipOperationParams operationParams =
         RelationshipOperationParams.builder()
@@ -157,8 +211,8 @@ void shouldMapOrderInGivenOrder()
 
   @Test
   void shouldMapNullOrderingParamsWhenNoOrderingParamsAreSpecified()
-      throws ForbiddenException, NotFoundException, BadRequestException {
-    when(trackedEntityService.getTrackedEntity(TE_UID)).thenReturn(trackedEntity);
+      throws ForbiddenException, NotFoundException {
+    when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity));
 
     RelationshipOperationParams operationParams =
         RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build();
diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java
index b006553f812e..aa145430cd11 100644
--- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java
+++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java
@@ -39,6 +39,7 @@
 import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
+import org.hisp.dhis.common.UidObject;
 import org.hisp.dhis.jsontree.JsonArray;
 import org.hisp.dhis.jsontree.JsonList;
 import org.hisp.dhis.jsontree.JsonObject;
@@ -124,16 +125,16 @@ public static void assertTrackedEntityWithinRelationshipItem(
         jsonTe.getTrackedEntityType(),
         "trackedEntityType UID");
     assertEquals(expected.getOrganisationUnit().getUid(), jsonTe.getOrgUnit(), "orgUnit UID");
-    assertTrue(jsonTe.getAttributes().isEmpty(), "attributes should be empty");
+    assertFalse(jsonTe.getAttributes().isEmpty(), "attributes should be empty");
     assertFalse(
         jsonTe.has("relationships"), "relationships is not returned within relationship items");
   }
 
-  public static void assertHasOnlyUid(String expectedUid, String member, JsonObject json) {
+  public static void assertHasOnlyUid(UidObject expected, String member, JsonObject json) {
     JsonObject j = json.getObject(member);
     assertFalse(j.isEmpty(), member + " should not be empty");
     assertHasOnlyMembers(j, member);
-    assertEquals(expectedUid, j.getString(member).string(), member + " UID");
+    assertEquals(expected.getUid(), j.getString(member).string(), member + " UID");
   }
 
   public static void assertEnrollmentWithinRelationship(
@@ -149,7 +150,7 @@ public static void assertEnrollmentWithinRelationship(
     assertEquals(expected.getFollowup(), jsonEnrollment.getFollowUp(), "followUp");
     assertEquals(
         expected.getOrganisationUnit().getUid(), jsonEnrollment.getOrgUnit(), "orgUnit UID");
-    assertTrue(jsonEnrollment.getArray("events").isEmpty(), "events should be empty");
+    assertFalse(jsonEnrollment.getArray("events").isEmpty(), "events should be empty");
     assertFalse(
         jsonEnrollment.has("relationships"),
         "relationships is not returned within relationship items");
diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java
index 3e688ac04e41..d18df071a797 100644
--- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java
+++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java
@@ -27,204 +27,175 @@
  */
 package org.hisp.dhis.webapi.controller.tracker.export.relationship;
 
-import static org.hisp.dhis.test.utils.Assertions.assertIsEmpty;
 import static org.hisp.dhis.test.utils.Assertions.assertStartsWith;
-import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertContainsAll;
+import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertContains;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertEnrollmentWithinRelationship;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertEventWithinRelationshipItem;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertFirstRelationship;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertHasOnlyMembers;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertHasOnlyUid;
-import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertNoRelationships;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertRelationship;
 import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertTrackedEntityWithinRelationshipItem;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
-import java.util.Date;
-import java.util.LinkedHashSet;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
-import org.hisp.dhis.category.CategoryOptionCombo;
-import org.hisp.dhis.category.CategoryService;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectManager;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.eventdatavalue.EventDataValue;
+import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundle;
+import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleMode;
+import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleParams;
+import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleService;
+import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleValidationService;
+import org.hisp.dhis.dxf2.metadata.objectbundle.feedback.ObjectBundleValidationReport;
 import org.hisp.dhis.http.HttpStatus;
+import org.hisp.dhis.importexport.ImportStrategy;
 import org.hisp.dhis.jsontree.JsonList;
-import org.hisp.dhis.jsontree.JsonObject;
-import org.hisp.dhis.note.Note;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Enrollment;
-import org.hisp.dhis.program.EnrollmentStatus;
 import org.hisp.dhis.program.Event;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.relationship.Relationship;
-import org.hisp.dhis.relationship.RelationshipConstraint;
-import org.hisp.dhis.relationship.RelationshipEntity;
-import org.hisp.dhis.relationship.RelationshipItem;
-import org.hisp.dhis.relationship.RelationshipType;
-import org.hisp.dhis.security.acl.AccessStringHelper;
+import org.hisp.dhis.render.RenderFormat;
+import org.hisp.dhis.render.RenderService;
 import org.hisp.dhis.test.webapi.PostgresControllerIntegrationTestBase;
 import org.hisp.dhis.trackedentity.TrackedEntity;
-import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
-import org.hisp.dhis.trackedentity.TrackedEntityProgramOwner;
-import org.hisp.dhis.trackedentity.TrackedEntityType;
-import org.hisp.dhis.trackedentity.TrackedEntityTypeAttribute;
-import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
-import org.hisp.dhis.trackerdataview.TrackerDataView;
+import org.hisp.dhis.tracker.imports.TrackerImportParams;
+import org.hisp.dhis.tracker.imports.TrackerImportService;
+import org.hisp.dhis.tracker.imports.domain.TrackerObjects;
+import org.hisp.dhis.tracker.imports.report.ImportReport;
+import org.hisp.dhis.tracker.imports.report.Status;
+import org.hisp.dhis.tracker.imports.report.ValidationReport;
 import org.hisp.dhis.user.User;
-import org.hisp.dhis.user.sharing.UserAccess;
-import org.hisp.dhis.webapi.controller.tracker.JsonAttribute;
-import org.hisp.dhis.webapi.controller.tracker.JsonDataValue;
 import org.hisp.dhis.webapi.controller.tracker.JsonNote;
-import org.hisp.dhis.webapi.controller.tracker.JsonProgramOwner;
 import org.hisp.dhis.webapi.controller.tracker.JsonRelationship;
-import org.hisp.dhis.webapi.controller.tracker.JsonRelationshipItem;
-import org.hisp.dhis.webapi.controller.tracker.JsonUser;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
 import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
 class RelationshipsExportControllerTest extends PostgresControllerIntegrationTestBase {
+  @Autowired private RenderService renderService;
 
-  @Autowired private IdentifiableObjectManager manager;
-
-  @Autowired private CategoryService categoryService;
-
-  private CategoryOptionCombo coc;
-
-  private OrganisationUnit orgUnit;
-
-  private OrganisationUnit anotherOrgUnit;
-
-  private Program program;
-
-  private ProgramStage programStage;
-
-  private User owner;
-
-  private User user;
+  @Autowired private ObjectBundleService objectBundleService;
 
-  private TrackedEntityType trackedEntityType;
+  @Autowired private ObjectBundleValidationService objectBundleValidationService;
 
-  private TrackedEntityAttribute tea;
+  @Autowired private TrackerImportService trackerImportService;
 
-  private TrackedEntityAttribute tea2;
+  @Autowired private IdentifiableObjectManager manager;
 
-  private DataElement dataElement;
+  private User importUser;
+
+  private Event relationship1To;
+  private Relationship relationship1;
+  private TrackedEntity relationship1From;
+  private Relationship relationship2;
+  private TrackedEntity relationship2From;
+  private Enrollment relationship2To;
+
+  protected ObjectBundle setUpMetadata(String path) throws IOException {
+    Map<Class<? extends IdentifiableObject>, List<IdentifiableObject>> metadata =
+        renderService.fromMetadata(new ClassPathResource(path).getInputStream(), RenderFormat.JSON);
+    ObjectBundleParams params = new ObjectBundleParams();
+    params.setObjectBundleMode(ObjectBundleMode.COMMIT);
+    params.setImportStrategy(ImportStrategy.CREATE);
+    params.setObjects(metadata);
+    ObjectBundle bundle = objectBundleService.create(params);
+    assertNoErrors(objectBundleValidationService.validate(bundle));
+    objectBundleService.commit(bundle);
+    return bundle;
+  }
+
+  protected TrackerObjects fromJson(String path) throws IOException {
+    return renderService.fromJson(
+        new ClassPathResource(path).getInputStream(), TrackerObjects.class);
+  }
+
+  @BeforeAll
+  void setUp() throws IOException {
+    setUpMetadata("tracker/simple_metadata.json");
+
+    importUser = userService.getUser("tTgjgobT1oS");
+    injectSecurityContextUser(importUser);
+
+    TrackerImportParams params = TrackerImportParams.builder().build();
+    assertNoErrors(
+        trackerImportService.importTracker(params, fromJson("tracker/event_and_enrollment.json")));
+
+    manager.flush();
+    manager.clear();
+
+    relationship1 = get(Relationship.class, "oLT07jKRu9e");
+    relationship1From = relationship1.getFrom().getTrackedEntity();
+    assertNotNull(relationship1From, "test expects 'from' to be a tracked entity");
+    relationship1To = relationship1.getTo().getEvent();
+    assertNotNull(relationship1To, "test expects 'to' to be an event");
+
+    relationship2 = get(Relationship.class, "p53a6314631");
+    relationship2From = relationship2.getFrom().getTrackedEntity();
+    assertNotNull(relationship2From, "test expects 'from' to be a tracked entity");
+    relationship2To = relationship2.getTo().getEnrollment();
+    assertNotNull(relationship2To, "test expects 'to' to be an enrollment");
+    // for some reason we get a LazyInit exception in an assertion when running all tests if we
+    // don't eagerly fetch like we do here
+    relationship2From.getUid();
+    relationship2To.getUid();
+    relationship2.getRelationshipType().getUid();
+  }
 
   @BeforeEach
-  void setUp() {
-    owner = makeUser("o");
-    manager.save(owner, false);
-
-    coc = categoryService.getDefaultCategoryOptionCombo();
-
-    orgUnit = createOrganisationUnit('A');
-    orgUnit.getSharing().setOwner(owner);
-    manager.save(orgUnit, false);
-
-    anotherOrgUnit = createOrganisationUnit('B');
-    anotherOrgUnit.getSharing().setOwner(owner);
-    manager.save(anotherOrgUnit, false);
-
-    user = createAndAddUser("tester", orgUnit);
-    user.setTeiSearchOrganisationUnits(Set.of(orgUnit));
-    this.userService.updateUser(user);
-
-    tea = createTrackedEntityAttribute('A');
-    tea.getSharing().setOwner(owner);
-    tea.getSharing().addUserAccess(userAccess());
-    manager.save(tea, false);
-
-    tea2 = createTrackedEntityAttribute('B');
-    tea2.getSharing().setOwner(owner);
-    tea2.getSharing().addUserAccess(userAccess());
-    manager.save(tea2, false);
-
-    trackedEntityType = trackedEntityTypeAccessible();
-
-    TrackedEntityTypeAttribute trackedEntityTypeAttribute =
-        new TrackedEntityTypeAttribute(trackedEntityType, tea);
-    trackedEntityTypeAttribute.setMandatory(false);
-    trackedEntityTypeAttribute.getSharing().setOwner(owner);
-    trackedEntityTypeAttribute.getSharing().addUserAccess(userAccess());
-    manager.save(trackedEntityTypeAttribute);
-
-    trackedEntityType.setTrackedEntityTypeAttributes(List.of(trackedEntityTypeAttribute));
-    manager.save(trackedEntityType, false);
-
-    program = createProgram('A');
-    program.addOrganisationUnit(orgUnit);
-    program.getSharing().setOwner(owner);
-    program.getSharing().addUserAccess(userAccess());
-    program.setTrackedEntityType(trackedEntityType);
-    manager.save(program, false);
-
-    programStage = createProgramStage('A', program);
-    programStage.getSharing().setOwner(owner);
-    programStage.getSharing().addUserAccess(userAccess());
-    manager.save(programStage, false);
-
-    dataElement = createDataElement('A');
-    manager.save(dataElement, false);
+  void setUpUser() {
+    switchContextToUser(importUser);
   }
 
   @Test
   void getRelationshipsById() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonRelationship relationship =
-        GET("/tracker/relationships/{uid}", r.getUid())
+    JsonRelationship jsonRelationship =
+        GET("/tracker/relationships/{uid}", relationship1.getUid())
             .content(HttpStatus.OK)
             .as(JsonRelationship.class);
 
     assertHasOnlyMembers(
-        relationship, "relationship", "relationshipType", "createdAtClient", "from", "to");
-    assertRelationship(r, relationship);
-    assertHasOnlyUid(from.getUid(), "event", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
+        jsonRelationship, "relationship", "relationshipType", "createdAtClient", "from", "to");
+    assertRelationship(relationship1, jsonRelationship);
+    assertHasOnlyUid(relationship1From, "trackedEntity", jsonRelationship.getObject("from"));
+    assertHasOnlyUid(relationship1To, "event", jsonRelationship.getObject("to"));
   }
 
   @Test
   void getRelationshipsByIdWithFieldsAll() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonRelationship relationship =
-        GET("/tracker/relationships/{uid}?fields=*", r.getUid())
+    JsonRelationship jsonRelationship =
+        GET("/tracker/relationships/{uid}?fields=*", relationship1.getUid())
             .content(HttpStatus.OK)
             .as(JsonRelationship.class);
 
-    assertRelationship(r, relationship);
-    assertEventWithinRelationshipItem(from, relationship.getFrom());
-    assertTrackedEntityWithinRelationshipItem(to, relationship.getTo());
+    assertRelationship(relationship1, jsonRelationship);
+    assertTrackedEntityWithinRelationshipItem(relationship1From, jsonRelationship.getFrom());
+    assertEventWithinRelationshipItem(relationship1To, jsonRelationship.getTo());
   }
 
   @Test
   void getRelationshipsByIdWithFields() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonRelationship relationship =
-        GET("/tracker/relationships/{uid}?fields=relationship,from[event]", r.getUid())
+    JsonRelationship jsonRelationship =
+        GET("/tracker/relationships/{uid}?fields=relationship,to[event]", relationship1.getUid())
             .content(HttpStatus.OK)
             .as(JsonRelationship.class);
 
-    assertHasOnlyMembers(relationship, "relationship", "from");
-    assertEquals(r.getUid(), relationship.getRelationship(), "relationship UID");
-    assertHasOnlyMembers(relationship.getObject("from"), "event");
-    assertEquals(from.getUid(), relationship.getFrom().getEvent().getEvent(), "event UID");
+    assertHasOnlyMembers(jsonRelationship, "relationship", "to");
+    assertEquals(relationship1.getUid(), jsonRelationship.getRelationship(), "relationship UID");
+    assertHasOnlyMembers(jsonRelationship.getObject("to"), "event");
+    assertEquals(
+        relationship1To.getUid(), jsonRelationship.getTo().getEvent().getEvent(), "event UID");
   }
 
   @Test
@@ -252,132 +223,132 @@ void getRelationshipsBadRequestWithMultipleParams() {
 
   @Test
   void getRelationshipsByEvent() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?event={uid}", from.getUid())
+    JsonList<JsonRelationship> jsonRelationships =
+        GET("/tracker/relationships?event={uid}", relationship1To.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    JsonObject relationship = assertFirstRelationship(r, relationships);
-    assertHasOnlyMembers(
-        relationship, "relationship", "relationshipType", "createdAtClient", "from", "to");
-    assertHasOnlyUid(from.getUid(), "event", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
+    JsonRelationship jsonRelationship =
+        assertContains(
+            jsonRelationships,
+            rel -> relationship1.getUid().equals(rel.getRelationship()),
+            "expected to find relationship " + relationship1.getUid());
+
+    assertRelationship(relationship1, jsonRelationship);
+    assertHasOnlyUid(relationship1From, "trackedEntity", jsonRelationship.getFrom());
+    assertHasOnlyUid(relationship1To, "event", jsonRelationship.getTo());
   }
 
   @Test
   void getRelationshipsByEventWithAllFields() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?event={uid}&fields=*", from.getUid())
+    JsonList<JsonRelationship> jsonRelationships =
+        GET("/tracker/relationships?event={uid}&fields=*", relationship1To.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    JsonRelationship relationship = assertFirstRelationship(r, relationships);
-    assertEventWithinRelationshipItem(from, relationship.getFrom());
-    assertTrackedEntityWithinRelationshipItem(to, relationship.getTo());
+    JsonRelationship jsonRelationship =
+        assertContains(
+            jsonRelationships,
+            rel -> relationship1.getUid().equals(rel.getRelationship()),
+            "expected to find relationship " + relationship1.getUid());
+
+    assertRelationship(relationship1, jsonRelationship);
+    assertTrackedEntityWithinRelationshipItem(relationship1From, jsonRelationship.getFrom());
+    assertEventWithinRelationshipItem(relationship1To, jsonRelationship.getTo());
   }
 
   @Test
   void getRelationshipsByEventWithFields() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?event={uid}&fields=relationship,from[event]", from.getUid())
+    JsonList<JsonRelationship> jsonRelationships =
+        GET(
+                "/tracker/relationships?event={uid}&fields=relationship,to[event]",
+                relationship1To.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    assertEquals(1, relationships.size(), "one relationship expected");
-    JsonRelationship relationship = relationships.get(0).as(JsonRelationship.class);
-    assertHasOnlyMembers(relationship, "relationship", "from");
-    assertEquals(r.getUid(), relationship.getRelationship(), "relationship UID");
-    assertHasOnlyMembers(relationship.getObject("from"), "event");
-    assertEquals(from.getUid(), relationship.getFrom().getEvent().getEvent(), "event UID");
-  }
+    JsonRelationship jsonRelationship =
+        assertContains(
+            jsonRelationships,
+            rel -> relationship1.getUid().equals(rel.getRelationship()),
+            "expected to find relationship " + relationship1.getUid());
 
-  @Test
-  void getRelationshipsByEventWithAssignedUser() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    from.setAssignedUser(owner);
-    relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?event={uid}&fields=from[event[assignedUser]]", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonUser user = relationships.get(0).getFrom().getEvent().getAssignedUser();
-    assertEquals(owner.getUid(), user.getUid());
-    assertEquals(owner.getUsername(), user.getUsername());
-  }
+    assertHasOnlyMembers(jsonRelationship, "relationship", "to");
+    assertHasOnlyMembers(jsonRelationship.getTo(), "event");
+    assertEquals(
+        relationship1To.getUid(), jsonRelationship.getTo().getEvent().getEvent(), "event UID");
+  }
+
+  // TODO(DHIS2-18883) migrate these tests
+  //  @Test
+  //  void getRelationshipsByEventWithAssignedUser() {
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?event={uid}&fields=from[event[assignedUser]]",
+  // from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonUser user = relationships.get(0).getFrom().getEvent().getAssignedUser();
+  //    assertEquals(owner.getUid(), user.getUid());
+  //    assertEquals(owner.getUsername(), user.getUsername());
+  //  }
+  //  @Test
+  //  void getRelationshipsByEventWithDataValues() {
+  //    TrackedEntity to = trackedEntity();
+  //    Event from = event(enrollment(to));
+  //    from.setEventDataValues(Set.of(new EventDataValue(dataElement.getUid(), "12")));
+  //    Relationship relationship = relationship(from, to);
+  //    RelationshipType type = relationship.getRelationshipType();
+  //
+  //    RelationshipConstraint toConstraint = new RelationshipConstraint();
+  //
+  //    TrackerDataView trackerDataView = new TrackerDataView();
+  //    trackerDataView.setDataElements(new LinkedHashSet<>(Set.of(dataElement.getUid())));
+  //
+  //    toConstraint.setTrackerDataView(trackerDataView);
+  //
+  //    type.setFromConstraint(toConstraint);
+  //
+  //    manager.update(type);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET(
+  //
+  // "/tracker/relationships?event={uid}&fields=from[event[dataValues[dataElement,value]]]",
+  //                from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonDataValue dataValue = relationships.get(0).getFrom().getEvent().getDataValues().get(0);
+  //    assertEquals(dataElement.getUid(), dataValue.getDataElement());
+  //    assertEquals("12", dataValue.getValue());
+  //  }
 
   @Test
-  void getRelationshipsByEventWithDataValues() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    from.setEventDataValues(Set.of(new EventDataValue(dataElement.getUid(), "12")));
-    Relationship relationship = relationship(from, to);
-    RelationshipType type = relationship.getRelationshipType();
-
-    RelationshipConstraint toConstraint = new RelationshipConstraint();
-
-    TrackerDataView trackerDataView = new TrackerDataView();
-    trackerDataView.setDataElements(new LinkedHashSet<>(Set.of(dataElement.getUid())));
-
-    toConstraint.setTrackerDataView(trackerDataView);
-
-    type.setFromConstraint(toConstraint);
-
-    manager.update(type);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
+  void getRelationshipsByEventWithNotes() {
+    JsonList<JsonRelationship> jsonRelationships =
         GET(
-                "/tracker/relationships?event={uid}&fields=from[event[dataValues[dataElement,value]]]",
-                from.getUid())
+                "/tracker/relationships?event={uid}&fields=relationship,to[event[notes]]",
+                relationship1To.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    JsonDataValue dataValue = relationships.get(0).getFrom().getEvent().getDataValues().get(0);
-    assertEquals(dataElement.getUid(), dataValue.getDataElement());
-    assertEquals("12", dataValue.getValue());
-  }
+    JsonRelationship jsonRelationship =
+        assertContains(
+            jsonRelationships,
+            rel -> relationship1.getUid().equals(rel.getRelationship()),
+            "expected to find relationship " + relationship1.getUid());
 
-  @Test
-  void getRelationshipsByEventWithNotes() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    from.setNotes(List.of(note("oqXG28h988k", "my notes", owner.getUid())));
-    relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?event={uid}&fields=from[event[notes]]", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonNote note = relationships.get(0).getFrom().getEvent().getNotes().get(0);
-    assertEquals("oqXG28h988k", note.getNote());
-    assertEquals("my notes", note.getValue());
-    assertEquals(owner.getUid(), note.getStoredBy());
+    JsonList<JsonNote> notes = jsonRelationship.getTo().getEvent().getNotes();
+    notes.forEach(
+        note -> {
+          assertHasOnlyMembers(note, "note", "value", "storedAt", "storedBy", "createdBy");
+        });
   }
 
   @Test
   void getRelationshipsByEventNotFound() {
-    switchContextToUser(user);
+    assertNull(manager.get(Event.class, "Hq3Kc6HK4OZ"), "test expects event not to exist");
 
     assertStartsWith(
         "Event with id Hq3Kc6HK4OZ",
@@ -386,114 +357,110 @@ void getRelationshipsByEventNotFound() {
 
   @Test
   void getRelationshipsByEnrollment() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?enrollment=" + from.getUid())
+    JsonList<JsonRelationship> jsonRelationships =
+        GET("/tracker/relationships?enrollment=" + relationship2To.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    JsonObject relationship = assertFirstRelationship(r, relationships);
-    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
-    assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
+    JsonRelationship jsonRelationship = assertFirstRelationship(relationship2, jsonRelationships);
+    assertHasOnlyMembers(jsonRelationship, "relationship", "relationshipType", "from", "to");
+    assertHasOnlyUid(relationship2From, "trackedEntity", jsonRelationship.getFrom());
+    assertHasOnlyUid(relationship2To, "enrollment", jsonRelationship.getTo());
   }
 
   @Test
   void getRelationshipsByEnrollmentWithFieldsAll() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?enrollment={uid}&fields=*", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonRelationship relationship = assertFirstRelationship(r, relationships);
-    assertEnrollmentWithinRelationship(from, relationship.getFrom());
-    assertTrackedEntityWithinRelationshipItem(to, relationship.getTo());
-  }
-
-  @Test
-  void getRelationshipsByEnrollmentWithEvents() {
-    Enrollment from = enrollment(trackedEntity());
-    Event to = event(from);
-    relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET(
-                "/tracker/relationships?enrollment={uid}&fields=from[enrollment[events[enrollment,event]]]",
-                from.getUid())
+    JsonList<JsonRelationship> jsonRelationships =
+        GET("/tracker/relationships?enrollment={uid}&fields=*", relationship2To.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    JsonRelationshipItem.JsonEvent event =
-        relationships.get(0).getFrom().getEnrollment().getEvents().get(0);
-    assertEquals(from.getUid(), event.getEnrollment());
-    assertEquals(to.getUid(), event.getEvent());
-  }
-
-  @Test
-  void getRelationshipsByEnrollmentWithAttributes() {
-    TrackedEntity to = trackedEntity();
-    to.setTrackedEntityAttributeValues(Set.of(attributeValue(tea, to, "12")));
-    program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea)));
-
-    Enrollment from = enrollment(to);
-    Relationship relationship = relationship(from, to);
-
-    RelationshipType type = relationship.getRelationshipType();
-
-    RelationshipConstraint constraint = new RelationshipConstraint();
-
-    TrackerDataView trackerDataView = new TrackerDataView();
-    trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid())));
-
-    constraint.setTrackerDataView(trackerDataView);
-
-    type.setFromConstraint(constraint);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET(
-                "/tracker/relationships?enrollment={uid}&fields=from[enrollment[attributes[attribute,value]]]",
-                from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonAttribute attribute = relationships.get(0).getFrom().getEnrollment().getAttributes().get(0);
-    assertEquals(tea.getUid(), attribute.getAttribute());
-    assertEquals("12", attribute.getValue());
-  }
-
-  @Test
-  void getRelationshipsByEnrollmentWithNotes() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    from.setNotes(List.of(note("oqXG28h988k", "my notes", owner.getUid())));
-    relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?enrollment={uid}&fields=from[enrollment[notes]]", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonNote note = relationships.get(0).getFrom().getEnrollment().getNotes().get(0);
-    assertEquals("oqXG28h988k", note.getNote());
-    assertEquals("my notes", note.getValue());
-    assertEquals(owner.getUid(), note.getStoredBy());
-  }
+    JsonRelationship jsonRelationship = assertFirstRelationship(relationship2, jsonRelationships);
+    assertTrackedEntityWithinRelationshipItem(relationship2From, jsonRelationship.getFrom());
+    assertEnrollmentWithinRelationship(relationship2To, jsonRelationship.getTo());
+  }
+
+  // TODO(DHIS2-18883) migrate these tests
+  //  @Test
+  //  void getRelationshipsByEnrollmentWithEvents() {
+  //    Enrollment from = enrollment(trackedEntity());
+  //    Event to = event(from);
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET(
+  //
+  // "/tracker/relationships?enrollment={uid}&fields=from[enrollment[events[enrollment,event]]]",
+  //                from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonRelationshipItem.JsonEvent event =
+  //        relationships.get(0).getFrom().getEnrollment().getEvents().get(0);
+  //    assertEquals(from.getUid(), event.getEnrollment());
+  //    assertEquals(to.getUid(), event.getEvent());
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByEnrollmentWithAttributes() {
+  //    TrackedEntity to = trackedEntity();
+  //    to.setTrackedEntityAttributeValues(Set.of(attributeValue(tea, to, "12")));
+  //    program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea)));
+  //
+  //    Enrollment from = enrollment(to);
+  //    Relationship relationship = relationship(from, to);
+  //
+  //    RelationshipType type = relationship.getRelationshipType();
+  //
+  //    RelationshipConstraint constraint = new RelationshipConstraint();
+  //
+  //    TrackerDataView trackerDataView = new TrackerDataView();
+  //    trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid())));
+  //
+  //    constraint.setTrackerDataView(trackerDataView);
+  //
+  //    type.setFromConstraint(constraint);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET(
+  //
+  // "/tracker/relationships?enrollment={uid}&fields=from[enrollment[attributes[attribute,value]]]",
+  //                from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonAttribute attribute =
+  // relationships.get(0).getFrom().getEnrollment().getAttributes().get(0);
+  //    assertEquals(tea.getUid(), attribute.getAttribute());
+  //    assertEquals("12", attribute.getValue());
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByEnrollmentWithNotes() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    from.setNotes(List.of(note("oqXG28h988k", "my notes", owner.getUid())));
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?enrollment={uid}&fields=from[enrollment[notes]]",
+  // from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonNote note = relationships.get(0).getFrom().getEnrollment().getNotes().get(0);
+  //    assertEquals("oqXG28h988k", note.getNote());
+  //    assertEquals("my notes", note.getValue());
+  //    assertEquals(owner.getUid(), note.getStoredBy());
+  //  }
 
   @Test
   void getRelationshipsByEnrollmentNotFound() {
-    switchContextToUser(user);
+    assertNull(manager.get(Enrollment.class, "Hq3Kc6HK4OZ"), "test expects event not to exist");
+
     assertStartsWith(
         "Enrollment with id Hq3Kc6HK4OZ",
         GET("/tracker/relationships?enrollment=Hq3Kc6HK4OZ")
@@ -503,555 +470,372 @@ void getRelationshipsByEnrollmentNotFound() {
 
   @Test
   void getRelationshipsByTrackedEntity() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", to.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonObject relationship = assertFirstRelationship(r, relationships);
-    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
-    assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
-  }
-
-  @Test
-  void shouldNotGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-
-    r.setDeleted(true);
-    manager.update(r);
-    switchContextToUser(user);
-
-    assertNoRelationships(
-        GET("/tracker/relationships?trackedEntity={te}", to.getUid()).content(HttpStatus.OK));
-  }
-
-  @Test
-  void shouldNotGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-
-    r.setDeleted(true);
-    manager.update(r);
-    switchContextToUser(user);
-
-    assertNoRelationships(
-        GET("/tracker/relationships?enrollment={en}", from.getUid()).content(HttpStatus.OK));
-  }
-
-  @Test
-  void shouldNotGetRelationshipsByEventWhenRelationshipIsDeleted() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-
-    r.setDeleted(true);
-    manager.update(r);
-    switchContextToUser(user);
-
-    assertNoRelationships(
-        GET("/tracker/relationships?event={ev}", from.getUid()).content(HttpStatus.OK));
-  }
-
-  @Test
-  void shouldGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-
-    r.setDeleted(true);
-    manager.update(r);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?trackedEntity={te}&includeDeleted=true", to.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    assertFirstRelationship(r, relationships);
-  }
-
-  @Test
-  void shouldGetRelationshipsByEventWhenRelationshipIsDeleted() {
-    TrackedEntity to = trackedEntity();
-    Event from = event(enrollment(to));
-    Relationship r = relationship(from, to);
-
-    r.setDeleted(true);
-    manager.update(r);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?event={ev}&includeDeleted=true", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    assertFirstRelationship(r, relationships);
-  }
-
-  @Test
-  void shouldGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-
-    r.setDeleted(true);
-    manager.update(r);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?enrollment={en}&includeDeleted=true", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    assertFirstRelationship(r, relationships);
-  }
-
-  @Test
-  void getRelationshipsByDeprecatedTei() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?tei=" + to.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonObject relationship = assertFirstRelationship(r, relationships);
-    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
-    assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
-  }
-
-  @Test
-  void getRelationshipsByTrackedEntityWithEnrollments() {
-    TrackedEntity to = trackedEntity();
-    Enrollment from = enrollment(to);
-    relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET(
-                "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[enrollments[enrollment,trackedEntity]]",
-                to.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonRelationshipItem.JsonEnrollment enrollment =
-        relationships.get(0).getTo().getTrackedEntity().getEnrollments().get(0);
-    assertEquals(from.getUid(), enrollment.getEnrollment());
-    assertEquals(to.getUid(), enrollment.getTrackedEntity());
-  }
-
-  @Test
-  void getRelationshipsByTrackedEntityAndEnrollmentWithAttributesIsEmpty() {
-    // Tracked entity attribute values are owned by the tracked entity and only mapped onto the
-    // enrollment on export. Program tracked entity attributes are only returned by the underlying
-    // TE service if a program is
-    // provided which is not possible on the relationship endpoint.
-    TrackedEntity to = trackedEntity(orgUnit);
-    to.setTrackedEntityAttributeValues(
-        Set.of(attributeValue(tea, to, "12"), attributeValue(tea2, to, "24")));
-    program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea2)));
-    Enrollment from = enrollment(to);
-    Relationship relationship = relationship(from, to);
-
-    RelationshipType type = relationship.getRelationshipType();
-
-    RelationshipConstraint fromConstraint = new RelationshipConstraint();
-
-    TrackerDataView trackerDataView = new TrackerDataView();
-    trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea2.getUid())));
-
-    fromConstraint.setTrackerDataView(trackerDataView);
-
-    RelationshipConstraint toConstraint = new RelationshipConstraint();
-
-    TrackerDataView dataView = new TrackerDataView();
-    dataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid(), tea2.getUid())));
-
-    toConstraint.setTrackerDataView(dataView);
-
-    type.setFromConstraint(fromConstraint);
-    type.setToConstraint(toConstraint);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET(
-                "/tracker/relationships?trackedEntity={trackedEntity}&fields=from[enrollment[attributes[attribute,value]]],to[trackedEntity[attributes[attribute,value]]]",
-                to.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonList<JsonAttribute> enrollmentAttr =
-        relationships.get(0).getFrom().getEnrollment().getAttributes();
-    assertIsEmpty(
-        enrollmentAttr.toList(JsonAttribute::getAttribute),
-        "program attributes should not be returned as no program can be provided");
-    JsonList<JsonAttribute> teAttributes =
-        relationships.get(0).getTo().getTrackedEntity().getAttributes();
-    assertContainsAll(List.of(tea.getUid()), teAttributes, JsonAttribute::getAttribute);
-    assertContainsAll(List.of("12"), teAttributes, JsonAttribute::getValue);
-  }
-
-  @Test
-  void getRelationshipsByTrackedEntityWithProgramOwners() {
-    TrackedEntity to = trackedEntity(orgUnit);
-    Enrollment from = enrollment(to);
-    to.setProgramOwners(Set.of(new TrackedEntityProgramOwner(to, from.getProgram(), orgUnit)));
-    relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET(
-                "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[programOwners]",
-                to.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonProgramOwner jsonProgramOwner =
-        relationships.get(0).getTo().getTrackedEntity().getProgramOwners().get(0);
-    assertEquals(orgUnit.getUid(), jsonProgramOwner.getOrgUnit());
-    assertEquals(to.getUid(), jsonProgramOwner.getTrackedEntity());
-    assertEquals(from.getProgram().getUid(), jsonProgramOwner.getProgram());
-  }
-
-  @Test
-  void getRelationshipsByTrackedEntityRelationshipTeToTe() {
-    TrackedEntity from = trackedEntity();
-    TrackedEntity to = trackedEntity();
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
-            .content(HttpStatus.OK)
-            .getList("relationships", JsonRelationship.class);
-
-    JsonObject relationship = assertFirstRelationship(r, relationships);
-    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
-    assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
-  }
-
-  @Test
-  void shouldRetrieveRelationshipWhenUserHasAccessToRelationship() {
-    TrackedEntity from = trackedEntity();
-    TrackedEntity to = trackedEntity();
-    Relationship r = relationship(from, to);
-    switchContextToUser(user);
-
-    JsonList<JsonRelationship> relationships =
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
+    JsonList<JsonRelationship> jsonRelationships =
+        GET("/tracker/relationships?trackedEntity={trackedEntity}", relationship1From.getUid())
             .content(HttpStatus.OK)
             .getList("relationships", JsonRelationship.class);
 
-    JsonObject relationship = assertFirstRelationship(r, relationships);
-    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
-    assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from"));
-    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
-  }
-
-  @Test
-  void getRelationshipsByTrackedEntityRelationshipsNoAccessToRelationshipType() {
-    TrackedEntity from = trackedEntity();
-    TrackedEntity to = trackedEntity();
-    relationship(relationshipTypeNotAccessible(), from, to);
-    switchContextToUser(user);
-
-    assertNoRelationships(
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
-            .content(HttpStatus.OK));
-  }
-
-  @Test
-  void shouldRetrieveNoRelationshipsWhenUserHasNoAccessToRelationshipItemTo() {
-    TrackedEntity from = trackedEntity();
-    TrackedEntity to = trackedEntityNotInSearchScope();
-    relationship(from, to);
-    switchContextToUser(user);
-
-    assertNoRelationships(
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
-            .content(HttpStatus.OK));
-  }
-
-  @Test
-  void shouldReturnForbiddenWhenUserHasNoAccessToRelationshipItemFrom() {
-    TrackedEntity from = trackedEntityNotInSearchScope();
-    TrackedEntity to = trackedEntity();
-    relationship(from, to);
-    switchContextToUser(user);
-
-    assertEquals(
-        HttpStatus.FORBIDDEN,
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status());
-  }
-
-  @Test
-  void
-      shouldReturnForbiddenWhenGetRelationshipsByTrackedEntityWithNotAccessibleTrackedEntityType() {
-    TrackedEntityType type = trackedEntityTypeNotAccessible();
-    TrackedEntity from = trackedEntity(type);
-    TrackedEntity to = trackedEntity(type);
-    relationship(from, to);
-    switchContextToUser(user);
+    JsonRelationship jsonRelationship =
+        assertContains(
+            jsonRelationships,
+            rel -> relationship1.getUid().equals(rel.getRelationship()),
+            "expected to find relationship " + relationship1.getUid());
 
+    assertRelationship(relationship1, jsonRelationship);
+    assertHasOnlyMembers(
+        jsonRelationship, "relationship", "relationshipType", "createdAtClient", "from", "to");
+    assertHasOnlyUid(relationship1From, "trackedEntity", jsonRelationship.getFrom());
+    assertHasOnlyUid(relationship1To, "event", jsonRelationship.getTo());
+  }
+
+  //
+  //  @Test
+  //  void shouldNotGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    Relationship r = relationship(from, to);
+  //
+  //    r.setDeleted(true);
+  //    manager.update(r);
+  //    switchContextToUser(user);
+  //
+  //    assertNoRelationships(
+  //        GET("/tracker/relationships?trackedEntity={te}", to.getUid()).content(HttpStatus.OK));
+  //  }
+  //
+  //  @Test
+  //  void shouldNotGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    Relationship r = relationship(from, to);
+  //
+  //    r.setDeleted(true);
+  //    manager.update(r);
+  //    switchContextToUser(user);
+  //
+  //    assertNoRelationships(
+  //        GET("/tracker/relationships?enrollment={en}", from.getUid()).content(HttpStatus.OK));
+  //  }
+  //
+  //  @Test
+  //  void shouldNotGetRelationshipsByEventWhenRelationshipIsDeleted() {
+  //    TrackedEntity to = trackedEntity();
+  //    Event from = event(enrollment(to));
+  //    Relationship r = relationship(from, to);
+  //
+  //    r.setDeleted(true);
+  //    manager.update(r);
+  //    switchContextToUser(user);
+  //
+  //    assertNoRelationships(
+  //        GET("/tracker/relationships?event={ev}", from.getUid()).content(HttpStatus.OK));
+  //  }
+  //
+  //  @Test
+  //  void shouldGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    Relationship r = relationship(from, to);
+  //
+  //    r.setDeleted(true);
+  //    manager.update(r);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?trackedEntity={te}&includeDeleted=true", to.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    assertFirstRelationship(r, relationships);
+  //  }
+  //
+  //  @Test
+  //  void shouldGetRelationshipsByEventWhenRelationshipIsDeleted() {
+  //    TrackedEntity to = trackedEntity();
+  //    Event from = event(enrollment(to));
+  //    Relationship r = relationship(from, to);
+  //
+  //    r.setDeleted(true);
+  //    manager.update(r);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?event={ev}&includeDeleted=true", from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    assertFirstRelationship(r, relationships);
+  //  }
+  //
+  //  @Test
+  //  void shouldGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    Relationship r = relationship(from, to);
+  //
+  //    r.setDeleted(true);
+  //    manager.update(r);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?enrollment={en}&includeDeleted=true", from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    assertFirstRelationship(r, relationships);
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByDeprecatedTei() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    Relationship r = relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?tei=" + to.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonObject relationship = assertFirstRelationship(r, relationships);
+  //    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
+  //    assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from"));
+  //    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByTrackedEntityWithEnrollments() {
+  //    TrackedEntity to = trackedEntity();
+  //    Enrollment from = enrollment(to);
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET(
+  //
+  // "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[enrollments[enrollment,trackedEntity]]",
+  //                to.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonRelationshipItem.JsonEnrollment enrollment =
+  //        relationships.get(0).getTo().getTrackedEntity().getEnrollments().get(0);
+  //    assertEquals(from.getUid(), enrollment.getEnrollment());
+  //    assertEquals(to.getUid(), enrollment.getTrackedEntity());
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByTrackedEntityAndEnrollmentWithAttributesIsEmpty() {
+  //    // Tracked entity attribute values are owned by the tracked entity and only mapped onto the
+  //    // enrollment on export. Program tracked entity attributes are only returned by the
+  // underlying
+  //    // TE service if a program is
+  //    // provided which is not possible on the relationship endpoint.
+  //    TrackedEntity to = trackedEntity(orgUnit);
+  //    to.setTrackedEntityAttributeValues(
+  //        Set.of(attributeValue(tea, to, "12"), attributeValue(tea2, to, "24")));
+  //    program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea2)));
+  //    Enrollment from = enrollment(to);
+  //    Relationship relationship = relationship(from, to);
+  //
+  //    RelationshipType type = relationship.getRelationshipType();
+  //
+  //    RelationshipConstraint fromConstraint = new RelationshipConstraint();
+  //
+  //    TrackerDataView trackerDataView = new TrackerDataView();
+  //    trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea2.getUid())));
+  //
+  //    fromConstraint.setTrackerDataView(trackerDataView);
+  //
+  //    RelationshipConstraint toConstraint = new RelationshipConstraint();
+  //
+  //    TrackerDataView dataView = new TrackerDataView();
+  //    dataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid(), tea2.getUid())));
+  //
+  //    toConstraint.setTrackerDataView(dataView);
+  //
+  //    type.setFromConstraint(fromConstraint);
+  //    type.setToConstraint(toConstraint);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET(
+  //
+  // "/tracker/relationships?trackedEntity={trackedEntity}&fields=from[enrollment[attributes[attribute,value]]],to[trackedEntity[attributes[attribute,value]]]",
+  //                to.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonList<JsonAttribute> enrollmentAttr =
+  //        relationships.get(0).getFrom().getEnrollment().getAttributes();
+  //    assertIsEmpty(
+  //        enrollmentAttr.toList(JsonAttribute::getAttribute),
+  //        "program attributes should not be returned as no program can be provided");
+  //    JsonList<JsonAttribute> teAttributes =
+  //        relationships.get(0).getTo().getTrackedEntity().getAttributes();
+  //    assertContainsAll(List.of(tea.getUid()), teAttributes, JsonAttribute::getAttribute);
+  //    assertContainsAll(List.of("12"), teAttributes, JsonAttribute::getValue);
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByTrackedEntityWithProgramOwners() {
+  //    TrackedEntity to = trackedEntity(orgUnit);
+  //    Enrollment from = enrollment(to);
+  //    to.setProgramOwners(Set.of(new TrackedEntityProgramOwner(to, from.getProgram(), orgUnit)));
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET(
+  //
+  // "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[programOwners]",
+  //                to.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonProgramOwner jsonProgramOwner =
+  //        relationships.get(0).getTo().getTrackedEntity().getProgramOwners().get(0);
+  //    assertEquals(orgUnit.getUid(), jsonProgramOwner.getOrgUnit());
+  //    assertEquals(to.getUid(), jsonProgramOwner.getTrackedEntity());
+  //    assertEquals(from.getProgram().getUid(), jsonProgramOwner.getProgram());
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByTrackedEntityRelationshipTeToTe() {
+  //    TrackedEntity from = trackedEntity();
+  //    TrackedEntity to = trackedEntity();
+  //    Relationship r = relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonObject relationship = assertFirstRelationship(r, relationships);
+  //    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
+  //    assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from"));
+  //    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
+  //  }
+  //
+  //  @Test
+  //  void shouldRetrieveRelationshipWhenUserHasAccessToRelationship() {
+  //    TrackedEntity from = trackedEntity();
+  //    TrackedEntity to = trackedEntity();
+  //    Relationship r = relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    JsonList<JsonRelationship> relationships =
+  //        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
+  //            .content(HttpStatus.OK)
+  //            .getList("relationships", JsonRelationship.class);
+  //
+  //    JsonObject relationship = assertFirstRelationship(r, relationships);
+  //    assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to");
+  //    assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from"));
+  //    assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to"));
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByTrackedEntityRelationshipsNoAccessToRelationshipType() {
+  //    TrackedEntity from = trackedEntity();
+  //    TrackedEntity to = trackedEntity();
+  //    relationship(relationshipTypeNotAccessible(), from, to);
+  //    switchContextToUser(user);
+  //
+  //    assertNoRelationships(
+  //        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
+  //            .content(HttpStatus.OK));
+  //  }
+  //
+  //  @Test
+  //  void shouldRetrieveNoRelationshipsWhenUserHasNoAccessToRelationshipItemTo() {
+  //    TrackedEntity from = trackedEntity();
+  //    TrackedEntity to = trackedEntityNotInSearchScope();
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    assertNoRelationships(
+  //        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid())
+  //            .content(HttpStatus.OK));
+  //  }
+  //
+  //  @Test
+  //  void shouldReturnForbiddenWhenUserHasNoAccessToRelationshipItemFrom() {
+  //    TrackedEntity from = trackedEntityNotInSearchScope();
+  //    TrackedEntity to = trackedEntity();
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    assertEquals(
+  //        HttpStatus.FORBIDDEN,
+  //        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status());
+  //  }
+  //
+  //  @Test
+  //  void
+  //
+  // shouldReturnForbiddenWhenGetRelationshipsByTrackedEntityWithNotAccessibleTrackedEntityType() {
+  //    TrackedEntityType type = trackedEntityTypeNotAccessible();
+  //    TrackedEntity from = trackedEntity(type);
+  //    TrackedEntity to = trackedEntity(type);
+  //    relationship(from, to);
+  //    switchContextToUser(user);
+  //
+  //    assertEquals(
+  //        HttpStatus.FORBIDDEN,
+  //        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status());
+  //  }
+  //
+  //  @Test
+  //  void getRelationshipsByTrackedEntityNotFound() {
+  //    assertStartsWith(
+  //        "TrackedEntity with id Hq3Kc6HK4OZ",
+  //        GET("/tracker/relationships?trackedEntity=Hq3Kc6HK4OZ")
+  //            .error(HttpStatus.NOT_FOUND)
+  //            .getMessage());
+  //  }
+
+  private <T extends IdentifiableObject> T get(Class<T> type, String uid) {
+    T t = manager.get(type, uid);
+    assertNotNull(
+        t,
+        () ->
+            String.format(
+                "'%s' with uid '%s' should have been created", type.getSimpleName(), uid));
+    return t;
+  }
+
+  public static void assertNoErrors(ImportReport report) {
+    assertNotNull(report);
     assertEquals(
-        HttpStatus.FORBIDDEN,
-        GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status());
-  }
-
-  @Test
-  void getRelationshipsByTrackedEntityNotFound() {
-    assertStartsWith(
-        "TrackedEntity with id Hq3Kc6HK4OZ",
-        GET("/tracker/relationships?trackedEntity=Hq3Kc6HK4OZ")
-            .error(HttpStatus.NOT_FOUND)
-            .getMessage());
-  }
-
-  private TrackedEntityType trackedEntityTypeAccessible() {
-    TrackedEntityType type = trackedEntityType('A');
-    type.getSharing().addUserAccess(userAccess());
-    manager.save(type, false);
-    return type;
-  }
-
-  private TrackedEntityType trackedEntityTypeNotAccessible() {
-    TrackedEntityType type = trackedEntityType('B');
-    manager.save(type, false);
-    return type;
-  }
-
-  private TrackedEntityType trackedEntityType(char uniqueChar) {
-    TrackedEntityType type = createTrackedEntityType(uniqueChar);
-    type.getSharing().setOwner(owner);
-    type.getSharing().setPublicAccess(AccessStringHelper.DEFAULT);
-    return type;
-  }
-
-  private TrackedEntity trackedEntity() {
-    TrackedEntity te = trackedEntity(orgUnit);
-    manager.save(te, false);
-    return te;
-  }
-
-  private TrackedEntity trackedEntityNotInSearchScope() {
-    TrackedEntity te = trackedEntity(anotherOrgUnit);
-    manager.save(te, false);
-    return te;
-  }
-
-  private TrackedEntity trackedEntity(TrackedEntityType trackedEntityType) {
-    TrackedEntity te = trackedEntity(orgUnit, trackedEntityType);
-    manager.save(te, false);
-    return te;
-  }
-
-  private TrackedEntity trackedEntity(OrganisationUnit orgUnit) {
-    TrackedEntity te = trackedEntity(orgUnit, trackedEntityType);
-    manager.save(te, false);
-    return te;
-  }
-
-  private TrackedEntity trackedEntity(
-      OrganisationUnit orgUnit, TrackedEntityType trackedEntityType) {
-    TrackedEntity te = createTrackedEntity(orgUnit, trackedEntityType);
-    te.getSharing().setPublicAccess(AccessStringHelper.DEFAULT);
-    te.getSharing().setOwner(owner);
-    return te;
-  }
-
-  private Enrollment enrollment(TrackedEntity te) {
-    Enrollment enrollment = new Enrollment(program, te, orgUnit);
-    enrollment.setAutoFields();
-    enrollment.setEnrollmentDate(new Date());
-    enrollment.setOccurredDate(new Date());
-    enrollment.setStatus(EnrollmentStatus.COMPLETED);
-    manager.save(enrollment, false);
-    te.setEnrollments(Set.of(enrollment));
-    manager.save(te, false);
-    return enrollment;
-  }
-
-  private Event event(Enrollment enrollment) {
-    Event event = new Event(enrollment, programStage, orgUnit, coc);
-    event.setAutoFields();
-    manager.save(event, false);
-    enrollment.setEvents(Set.of(event));
-    manager.save(enrollment, false);
-    return event;
-  }
-
-  private UserAccess userAccess() {
-    UserAccess a = new UserAccess();
-    a.setUser(user);
-    a.setAccess(AccessStringHelper.FULL);
-    return a;
-  }
-
-  private RelationshipType relationshipTypeAccessible(
-      RelationshipEntity from, RelationshipEntity to) {
-    RelationshipType type = relationshipType(from, to);
-    type.getSharing().addUserAccess(userAccess());
-    manager.save(type, false);
-    return type;
-  }
-
-  private RelationshipType relationshipTypeNotAccessible() {
-    return relationshipType(
-        RelationshipEntity.TRACKED_ENTITY_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE);
-  }
-
-  private RelationshipType relationshipType(RelationshipEntity from, RelationshipEntity to) {
-    RelationshipType type = createRelationshipType('A');
-    type.getFromConstraint().setRelationshipEntity(from);
-    type.getToConstraint().setRelationshipEntity(to);
-    type.getSharing().setOwner(owner);
-    type.getSharing().setPublicAccess(AccessStringHelper.DEFAULT);
-    manager.save(type, false);
-    return type;
-  }
-
-  private Relationship relationship(TrackedEntity from, TrackedEntity to) {
-
-    RelationshipType type =
-        relationshipTypeAccessible(
-            RelationshipEntity.TRACKED_ENTITY_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE);
-    return relationship(type, from, to);
-  }
-
-  private Relationship relationship(RelationshipType type, TrackedEntity from, TrackedEntity to) {
-    Relationship r = new Relationship();
-
-    RelationshipItem fromItem = new RelationshipItem();
-    fromItem.setTrackedEntity(from);
-    from.getRelationshipItems().add(fromItem);
-    r.setFrom(fromItem);
-    fromItem.setRelationship(r);
-
-    RelationshipItem toItem = new RelationshipItem();
-    toItem.setTrackedEntity(to);
-    to.getRelationshipItems().add(toItem);
-    r.setTo(toItem);
-    toItem.setRelationship(r);
-
-    r.setRelationshipType(type);
-    r.setKey(type.getUid());
-    r.setInvertedKey(type.getUid());
-    r.setAutoFields();
-    r.getSharing().setOwner(owner);
-    manager.save(r, false);
-    return r;
-  }
-
-  private Relationship relationship(Event from, TrackedEntity to) {
-    Relationship r = new Relationship();
-
-    RelationshipItem fromItem = new RelationshipItem();
-    fromItem.setEvent(from);
-    from.getRelationshipItems().add(fromItem);
-    r.setFrom(fromItem);
-    fromItem.setRelationship(r);
-
-    RelationshipItem toItem = new RelationshipItem();
-    toItem.setTrackedEntity(to);
-    to.getRelationshipItems().add(toItem);
-    r.setTo(toItem);
-    toItem.setRelationship(r);
-
-    RelationshipType type =
-        relationshipTypeAccessible(
-            RelationshipEntity.PROGRAM_STAGE_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE);
-    r.setRelationshipType(type);
-    r.setKey(type.getUid());
-    r.setInvertedKey(type.getUid());
-
-    r.setAutoFields();
-    r.getSharing().setOwner(owner);
-    r.setCreatedAtClient(new Date());
-    manager.save(r, false);
-    return r;
-  }
-
-  private void relationship(Enrollment from, Event to) {
-    Relationship r = new Relationship();
-
-    RelationshipItem fromItem = new RelationshipItem();
-    fromItem.setEnrollment(from);
-    from.getRelationshipItems().add(fromItem);
-    r.setFrom(fromItem);
-    fromItem.setRelationship(r);
-
-    RelationshipItem toItem = new RelationshipItem();
-    toItem.setEvent(to);
-    to.getRelationshipItems().add(toItem);
-    r.setTo(toItem);
-    toItem.setRelationship(r);
-
-    RelationshipType type =
-        relationshipTypeAccessible(
-            RelationshipEntity.PROGRAM_INSTANCE, RelationshipEntity.PROGRAM_STAGE_INSTANCE);
-    r.setRelationshipType(type);
-    r.setKey(type.getUid());
-    r.setInvertedKey(type.getUid());
-
-    r.setAutoFields();
-    r.getSharing().setOwner(owner);
-    manager.save(r, false);
-  }
-
-  private Relationship relationship(Enrollment from, TrackedEntity to) {
-    manager.save(from, false);
-    manager.save(to, false);
-
-    Relationship r = new Relationship();
-
-    RelationshipItem fromItem = new RelationshipItem();
-    fromItem.setEnrollment(from);
-    from.getRelationshipItems().add(fromItem);
-    r.setFrom(fromItem);
-    fromItem.setRelationship(r);
-
-    RelationshipItem toItem = new RelationshipItem();
-    toItem.setTrackedEntity(to);
-    to.getRelationshipItems().add(toItem);
-    r.setTo(toItem);
-    toItem.setRelationship(r);
-
-    RelationshipType type =
-        relationshipTypeAccessible(
-            RelationshipEntity.PROGRAM_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE);
-    r.setRelationshipType(type);
-    r.setKey(type.getUid());
-    r.setInvertedKey(type.getUid());
-
-    r.setAutoFields();
-    r.getSharing().setOwner(owner);
-    manager.save(r, false);
-    return r;
-  }
-
-  private TrackedEntityAttributeValue attributeValue(
-      TrackedEntityAttribute tea, TrackedEntity te, String value) {
-    return new TrackedEntityAttributeValue(tea, te, value);
-  }
-
-  private Note note(String uid, String value, String storedBy) {
-    Note note = new Note(value, storedBy);
-    note.setUid(uid);
-    manager.save(note, false);
-    return note;
+        Status.OK,
+        report.getStatus(),
+        errorMessage(
+            "Expected import with status OK, instead got:%n", report.getValidationReport()));
+  }
+
+  private static Supplier<String> errorMessage(String errorTitle, ValidationReport report) {
+    return () -> {
+      StringBuilder msg = new StringBuilder(errorTitle);
+      report
+          .getErrors()
+          .forEach(
+              e -> {
+                msg.append(e.getErrorCode());
+                msg.append(": ");
+                msg.append(e.getMessage());
+                msg.append('\n');
+              });
+      return msg.toString();
+    };
+  }
+
+  public static void assertNoErrors(ObjectBundleValidationReport report) {
+    assertNotNull(report);
+    List<String> errors = new ArrayList<>();
+    report.forEachErrorReport(err -> errors.add(err.toString()));
+    assertFalse(
+        report.hasErrorReports(), String.format("Expected no errors, instead got: %s%n", errors));
   }
 }
diff --git a/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json b/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json
index d4c339310e31..99d6ec612a5a 100644
--- a/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json
+++ b/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json
@@ -1180,7 +1180,7 @@
         "trackedEntity": "guVNoAerxWo"
       },
       "to": {
-        "enrollment": "nxP7UnKhomJ"
+        "enrollment": "ipBifypAQTo"
       }
     }
   ],