diff --git a/vorgang-manager-server/pom.xml b/vorgang-manager-server/pom.xml index 4e13b200987e7cfdba9230a683f6ebb6f1b7d724..b25865e7759f22793d02245ce707ba72cd06a375 100644 --- a/vorgang-manager-server/pom.xml +++ b/vorgang-manager-server/pom.xml @@ -60,6 +60,7 @@ <collaboration-manager.version>0.7.0</collaboration-manager.version> <archive-manager.version>0.3.0</archive-manager.version> <document-manager.version>1.2.0</document-manager.version> + <eingang-manager-interface.version>2.19.0-SNAPSHOT</eingang-manager-interface.version> <zip.version>2.11.5</zip.version> <jsoup.version>1.15.3</jsoup.version> @@ -171,6 +172,11 @@ <artifactId>api-lib-core</artifactId> <version>${api-lib.version}</version> </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>eingang-manager-interface</artifactId> + <version>${eingang-manager-interface.version}</version> + </dependency> <!-- Spring --> <dependency> diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteService.java new file mode 100644 index 0000000000000000000000000000000000000000..b1b2e73f0147c826ed60528e1b0ce39d8e13c86b --- /dev/null +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteService.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.vorgang.vorgang.redirect; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.springframework.stereotype.Service; + +import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.forwarder.RouteForwardingServiceGrpc; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; +import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor; +import io.grpc.stub.StreamObserver; +import lombok.RequiredArgsConstructor; +import net.devh.boot.grpc.client.inject.GrpcClient; + +@Service +class ForwardingRemoteService { + + @GrpcClient("forwarder") + private RouteForwardingServiceGrpc.RouteForwardingServiceStub routeForwardingServiceGrpc; + + public void forward(ForwardingRequest request) { + CompletableFuture<Void> responseFuture = new CompletableFuture<>(); + var requestStreamObserver = routeForwardingServiceGrpc.withInterceptors(new VorgangManagerClientCallContextAttachingInterceptor()) + .routeForwarding(new ForwardingResponseObserver(responseFuture)); + try { + responseFuture.get(); + } catch (InterruptedException | ExecutionException e) { + throw new TechnicalException("Forwarding failed", e); + } + } + + @RequiredArgsConstructor + static class ForwardingResponseObserver implements StreamObserver<GrpcRouteForwardingResponse> { + private final CompletableFuture<Void> future; + + @Override + public void onNext(GrpcRouteForwardingResponse value) { + // noop + } + + @Override + public void onError(Throwable t) { + future.completeExceptionally(t); + } + + @Override + public void onCompleted() { + future.complete(null); + } + } +} diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java index ed26c9e9850a1361531b70b36699b5ca92c08596..6af4a3cd03f5a786e9951d30683af55e3fd53962 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java @@ -35,7 +35,6 @@ import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @@ -56,10 +55,12 @@ import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import jakarta.mail.util.ByteArrayDataSource; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; @Service @Log4j2 +@RequiredArgsConstructor public class ForwardingService { static final String MAIL_TEMPLATE = "/mail/redirect.txt.ftlh"; @@ -87,26 +88,15 @@ public class ForwardingService { static final String SUBJECT_BESTAETIGUNG_TEMPL = "Ihr Antrag auf %s - Az: %s"; static final String ZIP_FILENAME_TMPL = "%s.zip"; - @Autowired - private ForwardingRepository repository; - - @Autowired - private Configuration freemarkerCfg; - @Autowired - private ZipBuilderService zipService; - - @Autowired - private MailService emailService; - - @Autowired - private VorgangService vorgangService; - + private final ForwardingRepository repository; + private final Configuration freemarkerCfg; + private final ZipBuilderService zipService; + private final MailService emailService; + private final VorgangService vorgangService; // TODO abhängigkeit entfernen - @Autowired - private StatusService statusService; - - @Autowired - private ApplicationEventPublisher publisher; + private final StatusService statusService; + private final ForwardingRemoteService forwardingRemoteService; + private final ApplicationEventPublisher publisher; @Value("${ozgcloud.redirect.mail-from}") private String mailFrom; @@ -332,5 +322,6 @@ public class ForwardingService { public void forward(ForwardingRequest request) { statusService.setStatusToWeitergeleitet(request.getVorgangId(), request.getVersion()); + forwardingRemoteService.forward(request); } } \ No newline at end of file diff --git a/vorgang-manager-server/src/main/resources/application-local.yml b/vorgang-manager-server/src/main/resources/application-local.yml index 6dc2ce987e221a66e9c5f7e74a23b8a82fe86557..d320959ed403f3d876855a97c6cfe3f13fddb37d 100644 --- a/vorgang-manager-server/src/main/resources/application-local.yml +++ b/vorgang-manager-server/src/main/resources/application-local.yml @@ -38,6 +38,10 @@ grpc: negotiationType: PLAINTEXT vorgang-manager: negotiationType: PLAINTEXT + forwarder: + address: static://127.0.0.1:9292 + negotiationType: PLAINTEXT + server: security: enabled: false diff --git a/vorgang-manager-server/src/main/resources/application.yml b/vorgang-manager-server/src/main/resources/application.yml index 7bf48c56cfe7b1d089dd2dc367d1b6bcdd25d09c..db37a3d59597564120aae7e596c1202b417bc44e 100644 --- a/vorgang-manager-server/src/main/resources/application.yml +++ b/vorgang-manager-server/src/main/resources/application.yml @@ -44,6 +44,8 @@ grpc: negotiationType: PLAINTEXT zufi-manager: negotiationType: TLS + forwarder: + negotiationType: TLS server: security: diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cf85265b4af60a6f4fa5c283940ad5f696de4a58 --- /dev/null +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteServiceTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.vorgang.vorgang.redirect; + +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.eingang.forwarder.RouteForwardingServiceGrpc; +import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor; + +class ForwardingRemoteServiceTest { + + @Mock + private RouteForwardingServiceGrpc.RouteForwardingServiceStub serviceStub; + @Spy + @InjectMocks + private ForwardingRemoteService service; + + @Nested + class TestForward { + + private final ForwardingRequest request = ForwardingRequestTestFactory.create(); + + @BeforeEach + void init() { + when(serviceStub.withInterceptors(any())).thenReturn(serviceStub); + } + + @Test + void shouldAttachClientCallContext() { + givenGrpcCallCompletedSuccessfully(); + + forward(); + + verify(serviceStub).withInterceptors(any(VorgangManagerClientCallContextAttachingInterceptor.class)); + } + + @Test + void shouldMakeGrpcCallToRouteForwarding() { + givenGrpcCallCompletedSuccessfully(); + + forward(); + + verify(serviceStub).routeForwarding(any(ForwardingRemoteService.ForwardingResponseObserver.class)); + } + + private void givenGrpcCallCompletedSuccessfully() { + when(serviceStub.routeForwarding(any())).thenAnswer(invocation -> { + ((ForwardingRemoteService.ForwardingResponseObserver) invocation.getArgument(0)).onCompleted(); + return null; + }); + } + + private void forward() { + service.forward(request); + } + } +} diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java index 1b864c7a9ab50c247178efd8d1346e87aff1e4f5..326cf45ddf0f6ea612311f599880cdb81e231d43 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java @@ -64,19 +64,16 @@ class ForwardingServiceTest { private ForwardingService service; @Mock private ForwardingRepository repository; - @Mock private ZipBuilderService zipService; - @Mock private MailService mailService; - @Mock private VorgangService vorgangService; - @Mock private StatusService statusService; - + @Mock + private ForwardingRemoteService remoteService; @Mock private ApplicationEventPublisher publisher; @@ -626,11 +623,24 @@ class ForwardingServiceTest { @Nested class TestForward { + private final ForwardingRequest request = ForwardingRequestTestFactory.create(); + @Test void shouldSetStatusToWeitergeleitet() { - service.forward(ForwardingRequestTestFactory.create()); + forward(); verify(statusService).setStatusToWeitergeleitet(VorgangTestFactory.ID, VorgangTestFactory.VERSION); } + + @Test + void shouldCallRemoteService() { + forward(); + + verify(remoteService).forward(request); + } + + private void forward() { + service.forward(request); + } } } \ No newline at end of file