diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java
index 0a041763..bf8a9c09 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java
@@ -13,15 +13,13 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
 
+import jakarta.annotation.PostConstruct;
 import java.util.List;
 import java.util.UUID;
-import java.util.function.BiConsumer;
 
 import static net.hostsharing.hsadminng.errors.Validate.validate;
-import static net.hostsharing.hsadminng.mapper.KeyValueMap.from;
 
 @RestController
-
 public class HsOfficeContactController implements HsOfficeContactsApi {
 
     @Autowired
@@ -30,9 +28,20 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
     @Autowired
     private StrictMapper mapper;
 
+    @Autowired
+    private HsOfficeContactFromResourceConverter<HsOfficeContactRbacEntity> contactFromResourceConverter;
+
     @Autowired
     private HsOfficeContactRbacRepository contactRepo;
 
+    @PostConstruct
+    public void init() {
+        // HOWTO: add a ModelMapper converter for a generic entity class to a ModelMapper to be used in a certain context
+        //  This @PostConstruct could be implemented in the converter, but only without generics.
+        //  But this converter is for HsOfficeContactRbacEntity and HsOfficeContactRealEntity.
+        mapper.addConverter(contactFromResourceConverter, HsOfficeContactInsertResource.class, HsOfficeContactRbacEntity.class);
+    }
+
     @Override
     @Transactional(readOnly = true)
     @Timed("app.office.contacts.api.getListOfContacts")
@@ -62,7 +71,7 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
 
         context.define(currentSubject, assumedRoles);
 
-        final var entityToSave = mapper.map(body, HsOfficeContactRbacEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
+        final var entityToSave = mapper.map(body, HsOfficeContactRbacEntity.class);
 
         final var saved = contactRepo.save(entityToSave);
 
@@ -128,11 +137,4 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
         final var mapped = mapper.map(saved, HsOfficeContactResource.class);
         return ResponseEntity.ok(mapped);
     }
-
-    @SuppressWarnings("unchecked")
-    final BiConsumer<HsOfficeContactInsertResource, HsOfficeContactRbacEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
-        entity.putPostalAddress(from(resource.getPostalAddress()));
-        entity.putEmailAddresses(from(resource.getEmailAddresses()));
-        entity.putPhoneNumbers(from(resource.getPhoneNumbers()));
-    };
 }
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactFromResourceConverter.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactFromResourceConverter.java
new file mode 100644
index 00000000..8ebcbc88
--- /dev/null
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactFromResourceConverter.java
@@ -0,0 +1,27 @@
+package net.hostsharing.hsadminng.hs.office.contact;
+
+import lombok.SneakyThrows;
+import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactInsertResource;
+import org.modelmapper.Converter;
+import org.modelmapper.spi.MappingContext;
+import org.springframework.stereotype.Component;
+
+import static net.hostsharing.hsadminng.mapper.KeyValueMap.from;
+
+// HOWTO: implement a ModelMapper converter which converts from a (JSON) resource instance to a generic entity instance (RBAC vs. REAL)
+@Component
+public class HsOfficeContactFromResourceConverter<E extends HsOfficeContact>
+        implements Converter<HsOfficeContactInsertResource, E> {
+
+    @Override
+    @SneakyThrows
+    public E convert(final MappingContext<HsOfficeContactInsertResource, E> context) {
+        final var resource = context.getSource();
+        final var entity = context.getDestinationType().getDeclaredConstructor().newInstance();
+        entity.setCaption(resource.getCaption());
+        entity.putPostalAddress(from(resource.getPostalAddress()));
+        entity.putEmailAddresses(from(resource.getEmailAddresses()));
+        entity.putPhoneNumbers(from(resource.getPhoneNumbers()));
+        return entity;
+    }
+}
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java
index 2c519849..6074c909 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java
@@ -3,8 +3,10 @@ package net.hostsharing.hsadminng.hs.office.partner;
 import io.micrometer.core.annotation.Timed;
 import net.hostsharing.hsadminng.context.Context;
 import net.hostsharing.hsadminng.errors.ReferenceNotFoundException;
+import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactFromResourceConverter;
 import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity;
 import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi;
+import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactInsertResource;
 import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource;
 import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
 import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource;
@@ -22,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
 
+import jakarta.annotation.PostConstruct;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
 import java.util.List;
@@ -41,6 +44,9 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
     @Autowired
     private StrictMapper mapper;
 
+    @Autowired
+    private HsOfficeContactFromResourceConverter<HsOfficeContactRealEntity> contactFromResourceConverter;
+
     @Autowired
     private HsOfficePartnerRbacRepository rbacPartnerRepo;
 
@@ -50,6 +56,11 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
     @PersistenceContext
     private EntityManager em;
 
+    @PostConstruct
+    public void init() {
+        mapper.addConverter(contactFromResourceConverter, HsOfficeContactInsertResource.class, HsOfficeContactRealEntity.class);
+    }
+
     @Override
     @Transactional(readOnly = true)
     @Timed("app.office.partners.api.getListOfPartners")
@@ -185,15 +196,18 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
     private void optionallyUpdateRelatedRelations(final HsOfficePartnerRbacEntity saved, final HsOfficePersonRealEntity previousPartnerPerson) {
         final var partnerPersonHasChanged = !saved.getPartnerRel().getHolder().getUuid().equals(previousPartnerPerson.getUuid());
         if (partnerPersonHasChanged) {
-            final var count = em.createNativeQuery("""
+            // self-debitors of the old partner-person become self-debitors of the new partner person
+            em.createNativeQuery("""
                 UPDATE hs_office.relation
                     SET holderUuid = :newPartnerPersonUuid
-                    WHERE type = 'DEBITOR' AND holderUuid = :oldPartnerPersonUuid AND anchorUuid = :oldPartnerPersonUuid
+                    WHERE type = 'DEBITOR' AND
+                          holderUuid = :oldPartnerPersonUuid AND anchorUuid = :oldPartnerPersonUuid
             """)
                     .setParameter("oldPartnerPersonUuid", previousPartnerPerson.getUuid())
                     .setParameter("newPartnerPersonUuid", saved.getPartnerRel().getHolder().getUuid())
                     .executeUpdate();
-            System.out.println(count); // FIXME: remove
+
+            // re-anchor all relations from the old partner person to the new partner persion
             em.createNativeQuery("""
                 UPDATE hs_office.relation
                     SET anchorUuid = :newPartnerPersonUuid
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java
index 5d36b602..5c176f93 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java
@@ -1,7 +1,7 @@
 package net.hostsharing.hsadminng.hs.office.partner;
 
 import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
-import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntityPatcher;
+import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationPatcher;
 import net.hostsharing.hsadminng.mapper.EntityPatcher;
 import net.hostsharing.hsadminng.mapper.StrictMapper;
 
@@ -26,7 +26,7 @@ class HsOfficePartnerEntityPatcher implements EntityPatcher<HsOfficePartnerPatch
     public void apply(final HsOfficePartnerPatchResource resource) {
 
         if (resource.getPartnerRel() != null) {
-            new HsOfficeRelationEntityPatcher(mapper, em, entity.getPartnerRel()).apply(resource.getPartnerRel());
+            new HsOfficeRelationPatcher(mapper, em, entity.getPartnerRel()).apply(resource.getPartnerRel());
         }
 
         if (resource.getDetails() != null) {
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntityPatcher.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcher.java
similarity index 90%
rename from src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntityPatcher.java
rename to src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcher.java
index a8b42bb1..1111059b 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntityPatcher.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcher.java
@@ -9,13 +9,13 @@ import net.hostsharing.hsadminng.mapper.StrictMapper;
 import jakarta.persistence.EntityManager;
 import jakarta.validation.ValidationException;
 
-public class HsOfficeRelationEntityPatcher implements EntityPatcher<HsOfficeRelationPatchResource> {
+public class HsOfficeRelationPatcher implements EntityPatcher<HsOfficeRelationPatchResource> {
 
     private final StrictMapper mapper;
     private final EntityManager em;
     private final HsOfficeRelation entity;
 
-    public HsOfficeRelationEntityPatcher(final StrictMapper mapper, final EntityManager em, final HsOfficeRelation entity) {
+    public HsOfficeRelationPatcher(final StrictMapper mapper, final EntityManager em, final HsOfficeRelation entity) {
         this.mapper = mapper;
         this.em = em;
         this.entity = entity;
diff --git a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java
index 2bf87f09..664b803c 100644
--- a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java
@@ -20,6 +20,7 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.data.repository.Repository;
 import org.springframework.web.bind.annotation.RestController;
 
+import jakarta.annotation.PostConstruct;
 import jakarta.persistence.Table;
 
 import java.lang.annotation.Annotation;
@@ -420,7 +421,7 @@ public class ArchitectureTest {
                     if (isGeneratedSpringRepositoryMethod(item, method)) {
                         continue;
                     }
-                    if (item.isAnnotatedWith(RestController.class) && !method.getModifiers().contains(PUBLIC)) {
+                    if (!method.getModifiers().contains(PUBLIC) || method.isAnnotatedWith(PostConstruct.class)) {
                         continue;
                     }
                     final var message = String.format(
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java
index 9a688367..074b3580 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java
@@ -1,6 +1,7 @@
 package net.hostsharing.hsadminng.hs.office.partner;
 
 import net.hostsharing.hsadminng.context.Context;
+import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactFromResourceConverter;
 import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRbacEntity;
 import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
 import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
@@ -38,7 +39,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 @WebMvcTest(HsOfficePartnerController.class)
-@Import({StrictMapper.class, DisableSecurityConfig.class})
+@Import({ StrictMapper.class, HsOfficeContactFromResourceConverter.class, DisableSecurityConfig.class})
 @ActiveProfiles("test")
 class HsOfficePartnerControllerRestTest {
 
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntityPatcherUnitTest.java
deleted file mode 100644
index f4acb10b..00000000
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntityPatcherUnitTest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package net.hostsharing.hsadminng.hs.office.relation;
-
-import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity;
-import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactInsertResource;
-import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonInsertResource;
-import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource;
-import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationPatchResource;
-import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
-import net.hostsharing.hsadminng.mapper.StrictMapper;
-import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
-import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.openapitools.jackson.nullable.JsonNullable;
-
-import jakarta.validation.ValidationException;
-import java.util.UUID;
-import java.util.stream.Stream;
-
-import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL_PERSON;
-import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.NATURAL_PERSON;
-import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.PARTNER;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchThrowable;
-import static org.assertj.core.api.Assumptions.assumeThat;
-import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
-import static org.mockito.Mockito.lenient;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-@TestInstance(PER_CLASS)
-@ExtendWith(MockitoExtension.class)
-class HsOfficeRelationEntityPatcherUnitTest extends PatchUnitTestBase<
-        HsOfficeRelationPatchResource,
-        HsOfficeRelation
-        > {
-
-    private static final UUID INITIAL_RELATION_UUID = UUID.randomUUID();
-    private static final UUID INITIAL_ANCHOR_UUID = UUID.randomUUID();
-    private static final UUID INITIAL_HOLDER_UUID = UUID.randomUUID();
-    private static final UUID INITIAL_CONTACT_UUID = UUID.randomUUID();
-
-    private static final UUID PATCHED_HOLDER_UUID = UUID.randomUUID();
-    private static HsOfficePersonInsertResource HOLDER_PATCH_RESOURCE = new HsOfficePersonInsertResource() {
-
-        {
-            setPersonType(HsOfficePersonTypeResource.NATURAL_PERSON);
-            setFamilyName("Patched-Holder-Family-Name");
-            setGivenName("Patched-Holder-Given-Name");
-        }
-    };
-    private static HsOfficePersonRealEntity PATCHED_HOLDER = HsOfficePersonRealEntity.builder()
-            .uuid(PATCHED_HOLDER_UUID)
-            .personType(NATURAL_PERSON)
-            .familyName("Patched-Holder-Family-Name")
-            .givenName("Patched-Holder-Given-Name")
-            .build();
-
-    private static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
-    private static HsOfficeContactInsertResource CONTACT_PATCH_RESOURCE = new HsOfficeContactInsertResource() {
-
-        {
-            setCaption("Patched-Contact-Caption");
-        }
-    };
-    private static HsOfficeContactRealEntity PATCHED_CONTACT = HsOfficeContactRealEntity.builder()
-            .uuid(PATCHED_CONTACT_UUID)
-            .caption("Patched-Contact-Caption")
-            .build();
-
-    @Mock
-    private EntityManagerWrapper emw;
-
-    private StrictMapper mapper = new StrictMapper(emw);
-
-    @BeforeEach
-    void initMocks() {
-        lenient().when(emw.getReference(HsOfficePersonRealEntity.class, PATCHED_HOLDER_UUID)).thenAnswer(
-                p -> PATCHED_HOLDER);
-        lenient().when(emw.getReference(HsOfficeContactRealEntity.class, PATCHED_CONTACT_UUID)).thenAnswer(
-                p -> PATCHED_CONTACT);
-    }
-
-    @Override
-    protected HsOfficeRelation newInitialEntity() {
-        final var entity = new HsOfficeRelationRealEntity();
-        entity.setUuid(INITIAL_RELATION_UUID);
-        entity.setType(PARTNER);
-        entity.setAnchor(HsOfficePersonRealEntity.builder()
-                .uuid(INITIAL_ANCHOR_UUID)
-                .personType(LEGAL_PERSON)
-                .tradeName("Initial-Anchor-Tradename")
-                .build());
-        entity.setHolder(HsOfficePersonRealEntity.builder()
-                .uuid(INITIAL_HOLDER_UUID)
-                .personType(NATURAL_PERSON)
-                .familyName("Initial-Holder-Family-Name")
-                .givenName("Initial-Holder-Given-Name")
-                .build());
-        entity.setContact(HsOfficeContactRealEntity.builder()
-                .uuid(INITIAL_CONTACT_UUID)
-                .caption("Initial-Contact-Caption")
-                .build());
-        return entity;
-    }
-
-    @Override
-    protected HsOfficeRelationPatchResource newPatchResource() {
-        return new HsOfficeRelationPatchResource();
-    }
-
-    @Override
-    protected HsOfficeRelationEntityPatcher createPatcher(final HsOfficeRelation relation) {
-        return new HsOfficeRelationEntityPatcher(mapper, emw, relation);
-    }
-
-    @Override
-    protected Stream<Property> propertyTestDescriptors() {
-        return Stream.of(
-                new JsonNullableProperty<>(
-                        "holderUuid",
-                        HsOfficeRelationPatchResource::setHolderUuid,
-                        PATCHED_HOLDER_UUID,
-                        HsOfficeRelation::setHolder,
-                        PATCHED_HOLDER),
-                new SimpleProperty<>(
-                        "holder",
-                        HsOfficeRelationPatchResource::setHolder,
-                        HOLDER_PATCH_RESOURCE,
-                        HsOfficeRelation::setHolder,
-                        withoutUuid(PATCHED_HOLDER))
-                        .notNullable(),
-
-                new JsonNullableProperty<>(
-                        "contactUuid",
-                        HsOfficeRelationPatchResource::setContactUuid,
-                        PATCHED_CONTACT_UUID,
-                        HsOfficeRelation::setContact,
-                        PATCHED_CONTACT),
-                new SimpleProperty<>(
-                        "contact",
-                        HsOfficeRelationPatchResource::setContact,
-                        CONTACT_PATCH_RESOURCE,
-                        HsOfficeRelation::setContact,
-                        withoutUuid(PATCHED_CONTACT))
-                        .notNullable()
-        );
-    }
-
-    @Override
-    protected void willPatchAllProperties() {
-        // this generic test does not work because either holder or holder.uuid can be set
-        assumeThat(true).isFalse();
-    }
-
-    @Test
-    void willThrowExceptionIfHolderAndHolderUuidAreGiven() {
-        // given
-        final var givenEntity = newInitialEntity();
-        final var patchResource = newPatchResource();
-        patchResource.setHolderUuid(JsonNullable.of(PATCHED_HOLDER_UUID));
-        patchResource.setHolder(HOLDER_PATCH_RESOURCE);
-
-        // when
-        final var exception = catchThrowable(() -> createPatcher(givenEntity).apply(patchResource));
-
-        // then
-        assertThat(exception).isInstanceOf(ValidationException.class)
-                .hasMessage("either \"holder\" or \"holder.uuid\" can be given, not both");
-    }
-
-    @Test
-    void willThrowExceptionIfContactAndContactUuidAreGiven() {
-        // given
-        final var givenEntity = newInitialEntity();
-        final var patchResource = newPatchResource();
-        patchResource.setContactUuid(JsonNullable.of(PATCHED_CONTACT_UUID));
-        patchResource.setContact(CONTACT_PATCH_RESOURCE);
-
-        // when
-        final var exception =  catchThrowable(() -> createPatcher(givenEntity).apply(patchResource));
-
-        // then
-        assertThat(exception).isInstanceOf(ValidationException.class)
-                .hasMessage("either \"contact\" or \"contact.uuid\" can be given, not both");
-    }
-
-    @Test
-    void willPersistNewHolder() {
-        // given
-        final var givenEntity = newInitialEntity();
-        final var patchResource = newPatchResource();
-        patchResource.setHolder(HOLDER_PATCH_RESOURCE);
-
-        // when
-        createPatcher(givenEntity).apply(patchResource);
-
-        // then
-        verify(emw, times(1)).persist(givenEntity.getHolder());
-    }
-
-    @Test
-    void willPersistNewContact() {
-        // given
-        final var givenEntity = newInitialEntity();
-        final var patchResource = newPatchResource();
-        patchResource.setContact(CONTACT_PATCH_RESOURCE);
-
-        // when
-        createPatcher(givenEntity).apply(patchResource);
-
-        // then
-        verify(emw, times(1)).persist(givenEntity.getContact());
-    }
-
-    private HsOfficePersonRealEntity withoutUuid(final HsOfficePersonRealEntity givenWithUuid) {
-        return givenWithUuid.toBuilder().uuid(null).build();
-    }
-
-    private HsOfficeContactRealEntity withoutUuid(final HsOfficeContactRealEntity givenWithUuid) {
-        return givenWithUuid.toBuilder().uuid(null).build();
-    }
-}
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcherUnitTest.java
index 72871086..8647fc19 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcherUnitTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationPatcherUnitTest.java
@@ -1,24 +1,38 @@
 package net.hostsharing.hsadminng.hs.office.relation;
 
+import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactFromResourceConverter;
 import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity;
+import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactInsertResource;
+import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonInsertResource;
+import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource;
 import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationPatchResource;
 import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
 import net.hostsharing.hsadminng.mapper.StrictMapper;
 import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
 import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
+import org.openapitools.jackson.nullable.JsonNullable;
 
+import jakarta.validation.ValidationException;
+import java.util.Map;
 import java.util.UUID;
 import java.util.stream.Stream;
 
+import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL_PERSON;
+import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.NATURAL_PERSON;
+import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.PARTNER;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.assertj.core.api.Assumptions.assumeThat;
 import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 @TestInstance(PER_CLASS)
 @ExtendWith(MockitoExtension.class)
@@ -27,38 +41,84 @@ class HsOfficeRelationPatcherUnitTest extends PatchUnitTestBase<
         HsOfficeRelation
         > {
 
-    static final UUID INITIAL_RELATION_UUID = UUID.randomUUID();
-    static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
+    private static final UUID INITIAL_RELATION_UUID = UUID.randomUUID();
+    private static final UUID INITIAL_ANCHOR_UUID = UUID.randomUUID();
+    private static final UUID INITIAL_HOLDER_UUID = UUID.randomUUID();
+    private static final UUID INITIAL_CONTACT_UUID = UUID.randomUUID();
+
+    private static final UUID PATCHED_HOLDER_UUID = UUID.randomUUID();
+    private static HsOfficePersonInsertResource HOLDER_PATCH_RESOURCE = new HsOfficePersonInsertResource();
+    {
+        {
+            HOLDER_PATCH_RESOURCE.setPersonType(HsOfficePersonTypeResource.NATURAL_PERSON);
+            HOLDER_PATCH_RESOURCE.setFamilyName("Patched-Holder-Family-Name");
+            HOLDER_PATCH_RESOURCE.setGivenName("Patched-Holder-Given-Name");
+        }
+    };
+    private static HsOfficePersonRealEntity PATCHED_HOLDER = HsOfficePersonRealEntity.builder()
+            .uuid(PATCHED_HOLDER_UUID)
+            .personType(NATURAL_PERSON)
+            .familyName("Patched-Holder-Family-Name")
+            .givenName("Patched-Holder-Given-Name")
+            .build();
+
+    private static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
+    private static HsOfficeContactInsertResource CONTACT_PATCH_RESOURCE = new HsOfficeContactInsertResource();
+    {
+        {
+            CONTACT_PATCH_RESOURCE.setCaption("Patched-Contact-Caption");
+            CONTACT_PATCH_RESOURCE.setEmailAddresses(Map.ofEntries(
+                    Map.entry("main", "patched@example.org")
+            ));
+        }
+    };
+    private static HsOfficeContactRealEntity PATCHED_CONTACT = HsOfficeContactRealEntity.builder()
+            .uuid(PATCHED_CONTACT_UUID)
+            .caption("Patched-Contact-Caption")
+            .emailAddresses(Map.ofEntries(
+                    Map.entry("main", "patched@example.org")
+            ))
+            .build();
 
     @Mock
-    EntityManagerWrapper emw;
+    private EntityManagerWrapper emw;
+
+    private StrictMapper mapper;
 
-    StrictMapper mapper = new StrictMapper(emw);
 
     @BeforeEach
-    void initMocks() {
-        lenient().when(emw.getReference(eq(HsOfficeContactRealEntity.class), any())).thenAnswer(invocation ->
-                HsOfficeContactRealEntity.builder().uuid(invocation.getArgument(1)).build());
-    }
+    void init() {
+        mapper = new StrictMapper(emw); // emw is injected after the constructor got called
+        mapper.addConverter(
+                    new HsOfficeContactFromResourceConverter<>(),
+                    HsOfficeContactInsertResource.class, HsOfficeContactRealEntity.class);
 
-    final HsOfficePersonRealEntity givenInitialAnchorPerson = HsOfficePersonRealEntity.builder()
-            .uuid(UUID.randomUUID())
-            .build();
-    final HsOfficePersonRealEntity givenInitialHolderPerson = HsOfficePersonRealEntity.builder()
-            .uuid(UUID.randomUUID())
-            .build();
-    final HsOfficeContactRealEntity givenInitialContact = HsOfficeContactRealEntity.builder()
-            .uuid(UUID.randomUUID())
-            .build();
+        lenient().when(emw.getReference(HsOfficePersonRealEntity.class, PATCHED_HOLDER_UUID)).thenAnswer(
+                p -> PATCHED_HOLDER);
+        lenient().when(emw.getReference(HsOfficeContactRealEntity.class, PATCHED_CONTACT_UUID)).thenAnswer(
+                p -> PATCHED_CONTACT);
+    }
 
     @Override
     protected HsOfficeRelation newInitialEntity() {
-        final var entity = new HsOfficeRelationRbacEntity();
+        final var entity = new HsOfficeRelationRealEntity();
         entity.setUuid(INITIAL_RELATION_UUID);
-        entity.setType(HsOfficeRelationType.REPRESENTATIVE);
-        entity.setAnchor(givenInitialAnchorPerson);
-        entity.setHolder(givenInitialHolderPerson);
-        entity.setContact(givenInitialContact);
+        entity.setType(PARTNER);
+        entity.setAnchor(HsOfficePersonRealEntity.builder()
+                .uuid(INITIAL_ANCHOR_UUID)
+                .personType(LEGAL_PERSON)
+                .tradeName("Initial-Anchor-Tradename")
+                .build());
+        entity.setHolder(HsOfficePersonRealEntity.builder()
+                .uuid(INITIAL_HOLDER_UUID)
+                .personType(NATURAL_PERSON)
+                .familyName("Initial-Holder-Family-Name")
+                .givenName("Initial-Holder-Given-Name")
+                .build());
+        entity.setContact(HsOfficeContactRealEntity.builder()
+                .uuid(INITIAL_CONTACT_UUID)
+                .caption("Initial-Contact-Caption")
+                .build());
         return entity;
     }
 
@@ -68,24 +128,114 @@ class HsOfficeRelationPatcherUnitTest extends PatchUnitTestBase<
     }
 
     @Override
-    protected HsOfficeRelationEntityPatcher createPatcher(final HsOfficeRelation relation) {
-        return new HsOfficeRelationEntityPatcher(mapper, emw, relation);
+    protected HsOfficeRelationPatcher createPatcher(final HsOfficeRelation relation) {
+        return new HsOfficeRelationPatcher(mapper, emw, relation);
     }
 
     @Override
     protected Stream<Property> propertyTestDescriptors() {
         return Stream.of(
                 new JsonNullableProperty<>(
-                        "contact",
+                        "holderUuid",
+                        HsOfficeRelationPatchResource::setHolderUuid,
+                        PATCHED_HOLDER_UUID,
+                        HsOfficeRelation::setHolder,
+                        PATCHED_HOLDER),
+                new SimpleProperty<>(
+                        "holder",
+                        HsOfficeRelationPatchResource::setHolder,
+                        HOLDER_PATCH_RESOURCE,
+                        HsOfficeRelation::setHolder,
+                        withoutUuid(PATCHED_HOLDER))
+                        .notNullable(),
+
+                new JsonNullableProperty<>(
+                        "contactUuid",
                         HsOfficeRelationPatchResource::setContactUuid,
                         PATCHED_CONTACT_UUID,
                         HsOfficeRelation::setContact,
-                        newContact(PATCHED_CONTACT_UUID))
+                        PATCHED_CONTACT),
+                new SimpleProperty<>(
+                        "contact",
+                        HsOfficeRelationPatchResource::setContact,
+                        CONTACT_PATCH_RESOURCE,
+                        HsOfficeRelation::setContact,
+                        withoutUuid(PATCHED_CONTACT))
                         .notNullable()
         );
     }
 
-    static HsOfficeContactRealEntity newContact(final UUID uuid) {
-        return HsOfficeContactRealEntity.builder().uuid(uuid).build();
+    @Override
+    protected void willPatchAllProperties() {
+        // this generic test does not work because either holder or holder.uuid can be set
+        assumeThat(true).isFalse();
+    }
+
+    @Test
+    void willThrowExceptionIfHolderAndHolderUuidAreGiven() {
+        // given
+        final var givenEntity = newInitialEntity();
+        final var patchResource = newPatchResource();
+        patchResource.setHolderUuid(JsonNullable.of(PATCHED_HOLDER_UUID));
+        patchResource.setHolder(HOLDER_PATCH_RESOURCE);
+
+        // when
+        final var exception = catchThrowable(() -> createPatcher(givenEntity).apply(patchResource));
+
+        // then
+        assertThat(exception).isInstanceOf(ValidationException.class)
+                .hasMessage("either \"holder\" or \"holder.uuid\" can be given, not both");
+    }
+
+    @Test
+    void willThrowExceptionIfContactAndContactUuidAreGiven() {
+        // given
+        final var givenEntity = newInitialEntity();
+        final var patchResource = newPatchResource();
+        patchResource.setContactUuid(JsonNullable.of(PATCHED_CONTACT_UUID));
+        patchResource.setContact(CONTACT_PATCH_RESOURCE);
+
+        // when
+        final var exception =  catchThrowable(() -> createPatcher(givenEntity).apply(patchResource));
+
+        // then
+        assertThat(exception).isInstanceOf(ValidationException.class)
+                .hasMessage("either \"contact\" or \"contact.uuid\" can be given, not both");
+    }
+
+    @Test
+    void willPersistNewHolder() {
+        // given
+        final var givenEntity = newInitialEntity();
+        final var patchResource = newPatchResource();
+        patchResource.setHolder(HOLDER_PATCH_RESOURCE);
+
+        // when
+        createPatcher(givenEntity).apply(patchResource);
+
+        // then
+        verify(emw, times(1)).persist(givenEntity.getHolder());
+    }
+
+    @Test
+    void willPersistNewContact() {
+        // given
+        final var givenEntity = newInitialEntity();
+        final var patchResource = newPatchResource();
+        patchResource.setContact(CONTACT_PATCH_RESOURCE);
+
+        // when
+        createPatcher(givenEntity).apply(patchResource);
+
+        // then
+        verify(emw, times(1)).persist(givenEntity.getContact());
+    }
+
+    private HsOfficePersonRealEntity withoutUuid(final HsOfficePersonRealEntity givenWithUuid) {
+        return givenWithUuid.toBuilder().uuid(null).build();
+    }
+
+    private HsOfficeContactRealEntity withoutUuid(final HsOfficeContactRealEntity givenWithUuid) {
+        return givenWithUuid.toBuilder().uuid(null).build();
     }
 }
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/partner/ReplaceDeceasedPartnerWithCommunityOfHeirs.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/partner/ReplaceDeceasedPartnerWithCommunityOfHeirs.java
index c114809b..1db638df 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/partner/ReplaceDeceasedPartnerWithCommunityOfHeirs.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/partner/ReplaceDeceasedPartnerWithCommunityOfHeirs.java
@@ -101,22 +101,43 @@ public class ReplaceDeceasedPartnerWithCommunityOfHeirs extends UseCase<ReplaceD
                 () -> httpGet("/api/hs/office/partners/%{partnerNumber}")
                         .expecting(OK).expecting(JSON).expectObject(),
                 path("partnerRel.holder.tradeName").contains(
-                        "Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}")
+                        "Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}"),
+                path("partnerRel.contact.postalAddress").lenientlyContainsJson("§{communityOfHeirsPostalAddress}"),
+                path("partnerRel.contact.phoneNumbers.office").contains("%{communityOfHeirsOfficePhoneNumber}"),
+                path("partnerRel.contact.emailAddresses.main").contains("%{communityOfHeirsEmailAddress}")
         );
 
-        // TODO.test: Verify the EX_PARTNER-Relation, once we fixed the anchor problem, see HsOfficePartnerController
-        // (net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerController.optionallyCreateExPartnerRelation)
+        verify(
+                "Verify the Ex-Partner-Relation",
+                () -> httpGet(
+                        "/api/hs/office/relations?relationType=EX_PARTNER&personUuid=%{Person: %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}}")
+                        .expecting(OK).expecting(JSON).expectArrayElements(1),
+                path("[0].anchor.tradeName").contains(
+                        "Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}")
+        );
 
         verify(
                 "Verify the Representative-Relation",
                 () -> httpGet(
-                        "/api/hs/office/relations?relationType=REPRESENTATIVE&personUuid=%{Person: %{representativeGivenName} %{representativeFamilyName}}")
+                        "/api/hs/office/relations?relationType=REPRESENTATIVE&personUuid=%{Person: Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}}")
                         .expecting(OK).expecting(JSON).expectArrayElements(1),
                 path("[0].anchor.tradeName").contains(
                         "Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}"),
-                path("[0].holder.familyName").contains("%{representativeFamilyName}")
+                path("[0].holder.familyName").contains("%{representativeFamilyName}"),
+                path("[0].contact.postalAddress").lenientlyContainsJson("§{communityOfHeirsPostalAddress}"),
+                path("[0].contact.phoneNumbers.office").contains("%{communityOfHeirsOfficePhoneNumber}"),
+                path("[0].contact.emailAddresses.main").contains("%{communityOfHeirsEmailAddress}")
         );
 
-        // TODO.test: Verify Debitor, Membership, Coop-Shares and Coop-Assets once implemented
+        verify(
+                "Verify the Debitor-Relation",
+                () -> httpGet(
+                        "/api/hs/office/debitors?partnerNumber=%{partnerNumber}")
+                        .expecting(OK).expecting(JSON).expectArrayElements(1),
+                path("[0].debitorRel.anchor.tradeName").contains(
+                        "Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}"),
+                path("[0].debitorRel.holder.tradeName").contains(
+                        "Erbengemeinschaft %{givenNameOfDeceasedPerson} %{familyNameOfDeceasedPerson}")
+        );
     }
 }
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/scenarios/PathAssertion.java b/src/test/java/net/hostsharing/hsadminng/hs/scenarios/PathAssertion.java
index 4a51932e..04ec0fe9 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/scenarios/PathAssertion.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/scenarios/PathAssertion.java
@@ -5,6 +5,7 @@ import net.hostsharing.hsadminng.hs.scenarios.UseCase.HttpResponse;
 import java.util.function.Consumer;
 
 import static net.hostsharing.hsadminng.hs.scenarios.TemplateResolver.Resolver.DROP_COMMENTS;
+import static net.hostsharing.hsadminng.test.JsonMatcher.lenientlyEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
 public class PathAssertion {
@@ -27,6 +28,18 @@ public class PathAssertion {
         };
     }
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public Consumer<UseCase.HttpResponse> lenientlyContainsJson(final String resolvableValue) {
+        return response -> {
+            try {
+                lenientlyEquals(ScenarioTest.resolve(resolvableValue, DROP_COMMENTS)).matches(response.getFromBody(path)) ;
+            } catch (final AssertionError e) {
+                // without this, the error message is often lacking important context
+                fail(e.getMessage() + " in `path(\"" + path +  "\").contains(\"" + resolvableValue + "\")`" );
+            }
+        };
+    }
+
     public Consumer<HttpResponse> doesNotExist() {
         return response -> {
             try {
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/scenarios/TemplateResolver.java b/src/test/java/net/hostsharing/hsadminng/hs/scenarios/TemplateResolver.java
index d28adb26..eb82d676 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/scenarios/TemplateResolver.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/scenarios/TemplateResolver.java
@@ -32,6 +32,12 @@ public class TemplateResolver {
                 return jsonQuoted(value);
             }
         },
+        JSON_OBJECT('§'){
+            @Override
+            String convert(final Object value, final Resolver resolver) {
+                return jsonObject(value);
+            }
+        },
         URI_ENCODED('&'){
             @Override
             String convert(final Object value, final Resolver resolver) {
@@ -213,4 +219,12 @@ public class TemplateResolver {
             default -> "\"" + value + "\"";
         };
     }
+
+    private static String jsonObject(final Object value) {
+        return switch (value) {
+            case null -> null;
+            case String string -> "{" + string.replace("\n", " ") + "}";
+            default -> throw new IllegalArgumentException("can not format " + value.getClass() + " (" + value + ") as JSON object");
+        };
+    }
 }