refactor(transcription/annotation): break mutual repo dependency
Some checks failed
CI / Unit & Component Tests (push) Failing after 4m2s
CI / OCR Service Tests (push) Successful in 42s
CI / Backend Unit Tests (push) Failing after 3m17s
CI / Unit & Component Tests (pull_request) Failing after 3m49s
CI / OCR Service Tests (pull_request) Successful in 39s
CI / Backend Unit Tests (pull_request) Failing after 3m17s

TranscriptionService injected AnnotationRepository; AnnotationService injected
TranscriptionBlockRepository. Each side now talks through the other domain's
service:

- TranscriptionService.deleteByAnnotationId — new write delegation; called
  from AnnotationService.deleteAnnotation in place of the foreign repo.
- AnnotationService.deleteById / deleteAllById — new write delegations; called
  from TranscriptionService for cascading annotation cleanup.
- AnnotationService.findById (added in #417 commit 6) replaces the read.
- @Lazy on AnnotationService's TranscriptionService field breaks the
  resulting two-bean cycle at construction time, mirroring the existing
  @Lazy self-reference pattern in SenderModelService.

Refs #417 (C6.2 violations #10 and #11).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-05 07:48:26 +02:00
parent f5151f3949
commit 2506523f3b
5 changed files with 33 additions and 22 deletions

View File

@@ -13,7 +13,6 @@ import org.raddatz.familienarchiv.dto.UpdateAnnotationDTO;
import org.raddatz.familienarchiv.exception.DomainException;
import org.raddatz.familienarchiv.model.DocumentAnnotation;
import org.raddatz.familienarchiv.repository.AnnotationRepository;
import org.raddatz.familienarchiv.repository.TranscriptionBlockRepository;
import org.springframework.dao.DataIntegrityViolationException;
import java.util.Map;
@@ -36,7 +35,7 @@ import static org.springframework.http.HttpStatus.NOT_FOUND;
class AnnotationServiceTest {
@Mock AnnotationRepository annotationRepository;
@Mock TranscriptionBlockRepository blockRepository;
@Mock TranscriptionService transcriptionService;
@Mock AuditService auditService;
@InjectMocks AnnotationService annotationService;
@@ -208,7 +207,7 @@ class AnnotationServiceTest {
annotationService.deleteAnnotation(docId, annotId, ownerId);
verify(blockRepository).deleteByAnnotationId(annotId);
verify(transcriptionService).deleteByAnnotationId(annotId);
verify(annotationRepository).delete(annotation);
}
@@ -225,8 +224,8 @@ class AnnotationServiceTest {
annotationService.deleteAnnotation(docId, annotId, ownerId);
var inOrder = org.mockito.Mockito.inOrder(blockRepository, annotationRepository);
inOrder.verify(blockRepository).deleteByAnnotationId(annotId);
var inOrder = org.mockito.Mockito.inOrder(transcriptionService, annotationRepository);
inOrder.verify(transcriptionService).deleteByAnnotationId(annotId);
inOrder.verify(annotationRepository).delete(annotation);
}

View File

@@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.audit.AuditService;
import org.raddatz.familienarchiv.model.BlockSource;
import org.raddatz.familienarchiv.model.TranscriptionBlock;
import org.raddatz.familienarchiv.repository.AnnotationRepository;
import org.raddatz.familienarchiv.repository.TranscriptionBlockRepository;
import org.raddatz.familienarchiv.repository.TranscriptionBlockVersionRepository;
@@ -20,7 +19,6 @@ class TranscriptionServiceGuidedTest {
TranscriptionBlockRepository blockRepository;
TranscriptionBlockVersionRepository versionRepository;
AnnotationRepository annotationRepository;
AnnotationService annotationService;
DocumentService documentService;
SenderModelService senderModelService;
@@ -35,14 +33,13 @@ class TranscriptionServiceGuidedTest {
void setUp() {
blockRepository = mock(TranscriptionBlockRepository.class);
versionRepository = mock(TranscriptionBlockVersionRepository.class);
annotationRepository = mock(AnnotationRepository.class);
annotationService = mock(AnnotationService.class);
documentService = mock(DocumentService.class);
senderModelService = mock(SenderModelService.class);
auditService = mock(AuditService.class);
service = new TranscriptionService(blockRepository, versionRepository,
annotationRepository, annotationService, documentService, senderModelService, auditService);
annotationService, documentService, senderModelService, auditService);
when(blockRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
when(versionRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));

View File

@@ -21,7 +21,6 @@ import org.raddatz.familienarchiv.model.PersonMention;
import org.raddatz.familienarchiv.model.ScriptType;
import org.raddatz.familienarchiv.model.TranscriptionBlock;
import org.raddatz.familienarchiv.model.TranscriptionBlockVersion;
import org.raddatz.familienarchiv.repository.AnnotationRepository;
import org.raddatz.familienarchiv.repository.TranscriptionBlockRepository;
import org.raddatz.familienarchiv.repository.TranscriptionBlockVersionRepository;
@@ -44,7 +43,6 @@ class TranscriptionServiceTest {
@Mock TranscriptionBlockRepository blockRepository;
@Mock TranscriptionBlockVersionRepository versionRepository;
@Mock AnnotationRepository annotationRepository;
@Mock AnnotationService annotationService;
@Mock DocumentService documentService;
@Mock SenderModelService senderModelService;
@@ -320,7 +318,7 @@ class TranscriptionServiceTest {
verify(blockRepository).delete(block);
verify(blockRepository).flush();
verify(annotationRepository).deleteById(annotId);
verify(annotationService).deleteById(annotId);
}
@Test
@@ -354,7 +352,7 @@ class TranscriptionServiceTest {
verify(blockRepository).deleteAll(List.of(block1, block2));
verify(blockRepository).flush();
verify(annotationRepository).deleteAllById(List.of(annId1, annId2));
verify(annotationService).deleteAllById(List.of(annId1, annId2));
}
@Test
@@ -532,7 +530,7 @@ class TranscriptionServiceTest {
when(blockRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
when(documentService.getDocumentById(any())).thenReturn(
Document.builder().scriptType(ScriptType.TYPEWRITER).build());
when(annotationRepository.findById(annotId)).thenReturn(Optional.of(annotation));
when(annotationService.findById(annotId)).thenReturn(Optional.of(annotation));
transcriptionService.updateBlock(docId, blockId, UpdateTranscriptionBlockDTO.builder().text("new text").build(), userId);