From 7a7d58a8e4893ab21d458f6f785820e0f4ed8c8a Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Wed, 15 Jan 2025 14:42:22 +0100
Subject: [PATCH 01/22] OZG-4094 beans: Condition on enabled=true

---
 .../postfach/osiv2/OsiPostfachRemoteService.java      |  3 ++-
 .../postfach/osiv2/config/ApiClientConfiguration.java |  6 +++---
 ...achProperties.java => Osi2PostfachProperties.java} | 11 ++++++-----
 .../osiv2/transfer/PostfachApiFacadeService.java      | 11 ++++++++---
 4 files changed, 19 insertions(+), 12 deletions(-)
 rename src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/{OsiPostfachProperties.java => Osi2PostfachProperties.java} (73%)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
index 6559227..8664f52 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
@@ -7,11 +7,12 @@ import org.springframework.stereotype.Service;
 
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
+import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
 import de.ozgcloud.nachrichten.postfach.osiv2.transfer.PostfachApiFacadeService;
 import lombok.extern.log4j.Log4j2;
 
 @Service
-@ConditionalOnProperty("ozgcloud.osiv2-postfach.enabled")
+@ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
 @Log4j2
 public record OsiPostfachRemoteService(
 		PostfachApiFacadeService postfachApiFacadeService
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
index 16d7d79..4584e52 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
@@ -23,11 +23,11 @@ import reactor.netty.transport.ProxyProvider;
 
 @Configuration
 @RequiredArgsConstructor
-@ConditionalOnProperty("ozgcloud.osiv2-postfach.enabled")
+@ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
 public class ApiClientConfiguration {
 
-	private final OsiPostfachProperties.ApiConfiguration apiConfiguration;
-	private final OsiPostfachProperties.ProxyConfiguration proxyConfiguration;
+	private final Osi2PostfachProperties.ApiConfiguration apiConfiguration;
+	private final Osi2PostfachProperties.ProxyConfiguration proxyConfiguration;
 
 	@Bean
 	MessageExchangeApi messageExchangeApi(ApiClient apiClient) {
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
similarity index 73%
rename from src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java
rename to src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
index 44fd8ef..2cf55ad 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
@@ -2,6 +2,7 @@ package de.ozgcloud.nachrichten.postfach.osiv2.config;
 
 import jakarta.annotation.Nullable;
 
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
 
@@ -11,10 +12,10 @@ import lombok.Setter;
 @Getter
 @Setter
 @Configuration
-@ConfigurationProperties(prefix = OsiPostfachProperties.PREFIX)
-public class OsiPostfachProperties {
+@ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
+public class Osi2PostfachProperties {
 
-	static final String PREFIX = "ozgcloud.osiv2-postfach";
+	public static final String PREFIX = "ozgcloud.osiv2-postfach";
 
 	private boolean enabled;
 
@@ -23,7 +24,7 @@ public class OsiPostfachProperties {
 	@Configuration
 	@ConfigurationProperties(prefix = ApiConfiguration.PREFIX)
 	static class ApiConfiguration {
-		static final String PREFIX = OsiPostfachProperties.PREFIX + ".api";
+		static final String PREFIX = Osi2PostfachProperties.PREFIX + ".api";
 
 		private String resource;
 		private String url;
@@ -40,7 +41,7 @@ public class OsiPostfachProperties {
 	@Configuration
 	@ConfigurationProperties(prefix = ProxyConfiguration.PREFIX)
 	static class ProxyConfiguration {
-		static final String PREFIX = OsiPostfachProperties.PREFIX + ".http-proxy";
+		static final String PREFIX = Osi2PostfachProperties.PREFIX + ".http-proxy";
 
 		private boolean enabled;
 
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
index 246a121..4405c98 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
@@ -7,16 +7,21 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.api.MessageExchangeApi;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
 import lombok.extern.log4j.Log4j2;
 
 @Log4j2
 @Service
-@ConditionalOnProperty("ozgcloud.osiv2-postfach.enabled")
-public record PostfachApiFacadeService(MessageExchangeApi messageExchangeApi, RequestMapper requestMapper, ResponseMapper responseMapper) {
-
+@ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
+public record PostfachApiFacadeService(
+		MessageExchangeApi messageExchangeApi,
+		RequestMapper requestMapper,
+		ResponseMapper responseMapper
+) {
 	private static int MAX_NUMBER_RECEIVED_MESSAGES = 100;
+
 	public void sendMessage(PostfachNachricht nachricht) {
 		messageExchangeApi.sendMessage(
 				requestMapper.mapMailboxId(nachricht),
-- 
GitLab


From 47f503cc56c3cd73c038273b3a98e4ec0d80b002 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 17 Jan 2025 08:57:48 +0100
Subject: [PATCH 02/22] OZG-4094 send: Use OSI Postfach-type

---
 .../nachrichten/postfach/osiv2/OsiPostfachRemoteService.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
index 8664f52..0d94013 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
@@ -17,7 +17,7 @@ import lombok.extern.log4j.Log4j2;
 public record OsiPostfachRemoteService(
 		PostfachApiFacadeService postfachApiFacadeService
 ) implements PostfachRemoteService {
-	public static final String POSTFACH_TYPE_OSI = "OSIV2";
+	public static final String POSTFACH_TYPE_OSI = "OSI";
 
 	@Override
 	public void sendMessage(PostfachNachricht nachricht) {
-- 
GitLab


From 4089276d22902a310c0d0131f732d396b61e2718 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 17 Jan 2025 09:11:04 +0100
Subject: [PATCH 03/22] OZG-4094 config: Disable osiv2 by default

---
 src/main/resources/application.yml        | 4 +---
 src/test/resources/application-itcase.yml | 3 +++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 172d0ad..1d1f1bf 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,6 +1,4 @@
 spring:
-  main:
-    web-application-type: reactive
   jackson:
     default-property-inclusion: NON_NULL
   security:
@@ -18,7 +16,7 @@ spring:
             token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token'
 ozgcloud:
   osiv2-postfach:
-    enabled: true
+    enabled: false
     api:
       resource: 'urn:dataport:osi:postfach:rz2:stage:sh'
       url: 'https://api-gateway-stage.dataport.de:443/api/osi_postfach/1.0.0'
diff --git a/src/test/resources/application-itcase.yml b/src/test/resources/application-itcase.yml
index dcbea65..d8cacf7 100644
--- a/src/test/resources/application-itcase.yml
+++ b/src/test/resources/application-itcase.yml
@@ -1,3 +1,6 @@
+ozgcloud:
+  osiv2-postfach:
+    enabled: true
 logging:
   level:
     de.ozgcloud.nachrichten.postfach.osiv2: DEBUG
-- 
GitLab


From c51bd8472202ba44afc1c0cd47fef73d613f52ca Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 20 Jan 2025 09:49:14 +0100
Subject: [PATCH 04/22] OZG-4094 beans: Turn records to classes

---
 .../postfach/osiv2/OsiPostfachRemoteService.java    |  8 +++++---
 .../osiv2/transfer/PostfachApiFacadeService.java    | 13 ++++++++-----
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
index 0d94013..a3d3ccd 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
@@ -9,14 +9,16 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
 import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
 import de.ozgcloud.nachrichten.postfach.osiv2.transfer.PostfachApiFacadeService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Service
 @ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
 @Log4j2
-public record OsiPostfachRemoteService(
-		PostfachApiFacadeService postfachApiFacadeService
-) implements PostfachRemoteService {
+@RequiredArgsConstructor
+public class OsiPostfachRemoteService implements PostfachRemoteService {
+	private final PostfachApiFacadeService postfachApiFacadeService;
+
 	public static final String POSTFACH_TYPE_OSI = "OSI";
 
 	@Override
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
index 4405c98..d3aaa13 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
@@ -10,16 +10,19 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.api.MessageExchangeApi;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Log4j2
 @Service
 @ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
-public record PostfachApiFacadeService(
-		MessageExchangeApi messageExchangeApi,
-		RequestMapper requestMapper,
-		ResponseMapper responseMapper
-) {
+@RequiredArgsConstructor
+public class PostfachApiFacadeService {
+
+	private final MessageExchangeApi messageExchangeApi;
+	private final RequestMapper requestMapper;
+	private final  ResponseMapper responseMapper;
+
 	private static int MAX_NUMBER_RECEIVED_MESSAGES = 100;
 
 	public void sendMessage(PostfachNachricht nachricht) {
-- 
GitLab


From 1c915ef750e2ab0859ff69025d495c42e2297534 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 24 Jan 2025 09:48:36 +0100
Subject: [PATCH 05/22] OZG-4095 refactor: Cleanup ITCase

---
 .../osiv2/OsiPostfachRemoteServiceITCase.java | 126 ++++++++----------
 .../postfach/osiv2/factory/JsonUtil.java      |   4 +-
 2 files changed, 56 insertions(+), 74 deletions(-)

diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
index eaf8f54..2771bbd 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -7,17 +7,14 @@ import static org.mockserver.mock.OpenAPIExpectation.*;
 import static org.mockserver.model.HttpRequest.*;
 import static org.mockserver.model.HttpResponse.*;
 
-import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.time.OffsetDateTime;
 import java.util.Arrays;
 import java.util.Map;
-import java.util.Objects;
 import java.util.UUID;
 
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -30,18 +27,14 @@ import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
 import org.springframework.test.context.TestPropertySource;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.extension.Jwt;
 import de.ozgcloud.nachrichten.postfach.osiv2.extension.OsiMockServerExtension;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.JsonUtil;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageFactory;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessagesResponse;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyMessage;
 import lombok.SneakyThrows;
 
 @SpringBootTest(classes = TestApplication.class)
@@ -49,11 +42,16 @@ import lombok.SneakyThrows;
 @TestPropertySource(properties = {
 		"ozgcloud.osiv2-postfach.http-proxy.enabled=false",
 })
-public class OsiPostfachRemoteServiceITCase {
+class OsiPostfachRemoteServiceITCase {
 
 	@RegisterExtension
 	static final OsiMockServerExtension OSI_MOCK_SERVER_EXTENSION = new OsiMockServerExtension();
 
+	@SneakyThrows
+	private static String getPostfachApiSpec() {
+		return Files.readString(Path.of("spec", "postfach-api-facade.yaml"));
+	}
+
 	private final PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create();
 
 	@Autowired
@@ -76,19 +74,13 @@ public class OsiPostfachRemoteServiceITCase {
 		postfachFacadeMockClient = OSI_MOCK_SERVER_EXTENSION.getPostfachFacadeMockClient();
 	}
 
-//	@Disabled
-	@DisplayName("should send dummy request with jwt")
+	@DisplayName("should send request with jwt")
 	@Test
 	@SneakyThrows
-	void shouldSendDummyRequestWithJwt() {
-		postfachFacadeMockClient.upsert(
-				openAPIExpectation()
-						.withSpecUrlOrPayload(Files.readString(Path.of("spec", "postfach-api-facade.yaml")))
-						.withOperationsAndResponses(Map.of(
-								"SendMessage", "200"
-						))
-		);
-
+	void shouldSendRequestWithJwt() {
+		mockOperationsAndResponses(Map.of(
+				"SendMessage", "200"
+		));
 
 		osiPostfachRemoteService.sendMessage(postfachNachricht);
 
@@ -101,89 +93,77 @@ public class OsiPostfachRemoteServiceITCase {
 		assertThat(jwt.body().read("$.aud", String.class)).isEqualTo(RESOURCE_URN);
 	}
 
-	ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
-
-	@Disabled
 	@DisplayName("should receive one messages")
 	@Test
 	@SneakyThrows
 	void shouldReceiveMessages() {
-		var uuid = UUID.fromString("00000000-0000-0000-0000-000000000000");
-
-		createMessagesJson(uuid, null);
-
-		createOneReplyMessageJson(uuid);
+		mockPostfachMessageAndResponse("00000000-0000-0000-0000-000000000000");
 
-		var messageStream = osiPostfachRemoteService.getAllMessages();
+		var messageList = osiPostfachRemoteService.getAllMessages().toList();
 
-		var messageList = messageStream.toList();
-		assertThat(messageList).size().isEqualTo(1);
+		assertThat(messageList).hasSize(1);
 	}
 
-	@Disabled
 	@DisplayName("should receive two messages")
 	@Test
 	@SneakyThrows
 	void shouldReceiveTwoMessages() {
-		var uuid1 = UUID.fromString("00000000-0000-0000-0000-000000000000");
-		var uuid2 = UUID.fromString("00000000-0000-0000-0000-000000000001");
+		mockPostfachMessageAndResponse("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000001");
 
-		createMessagesJson(uuid1, uuid2);
+		var messageList = osiPostfachRemoteService.getAllMessages().toList();
 
-		createOneReplyMessageJson(uuid1);
-		createOneReplyMessageJson(uuid2);
-
-		var messageStream = osiPostfachRemoteService.getAllMessages();
-
-		var messageList = messageStream.toList();
-		assertThat(messageList).size().isEqualTo(2);
+		assertThat(messageList).hasSize(2);
 	}
 
-	private void createMessagesJson(final UUID... uuids) throws IOException {
-		var messagesList = Arrays.stream(uuids).filter(Objects::nonNull).map(uuid -> new MessageExchangeReceiveMessage().guid(uuid)).toList();
-
-		var messages = new MessageExchangeReceiveMessagesResponse().messages(messagesList);
-
-		ObjectWriter ow = objectMapper.writer().withDefaultPrettyPrinter();
-		String messagesJson = ow.writeValueAsString(messages);
-
-		createMessagesCall("receiveMessages", messagesJson);
+	private void mockPostfachMessageAndResponse(final String... uuids) {
+		// Stub message listing response
+		mockJsonOperation("receiveMessages", new MessageExchangeReceiveMessagesResponse()
+				.messages(Arrays.stream(uuids)
+						.map(uuid -> new MessageExchangeReceiveMessage()
+								.guid(UUID.fromString(uuid)))
+						.toList()));
+		for (String uuid : uuids) {
+			// Stub individual response for message
+			mockJsonOperation("getMessage", V1ReplyMessageFactory.create()
+					.messageBox(UUID.fromString(uuid))
+					.responseTime(OffsetDateTime.now()));
+		}
 	}
 
-	private void createMessagesCall(final String receiveMessages, final String messagesJson) throws IOException {
+	private void mockJsonOperation(final String operationId, final Object body) {
 		postfachFacadeMockClient
 				.when(
 						new OpenAPIDefinition()
-								.withSpecUrlOrPayload(Files.readString(Path.of("spec", "postfach-api-facade.yaml")))
-								.withOperationId(receiveMessages)
+								.withSpecUrlOrPayload(getPostfachApiSpec())
+								.withOperationId(operationId)
 				)
-				.respond(response().withHeader("Content-type", "application/json").withBody(messagesJson));
+				.respond(
+						response()
+								.withHeader("Content-type", "application/json")
+								.withBody(JsonUtil.toJson(body))
+				);
 	}
 
-	private void createOneReplyMessageJson(final UUID uuid) throws IOException {
-		ObjectWriter ow = objectMapper.writer().withDefaultPrettyPrinter();
-
-		var replyMessage = new V1ReplyMessage()
-				.body("das ist ein toller Body").replyAction(V1ReplyBehavior.REPLYPOSSIBLE).messageBox(uuid).responseTime(OffsetDateTime.now());
-		String messageJson = ow.writeValueAsString(replyMessage);
-
-		createMessagesCall("getMessage", messageJson);
-	}
-
-	@Disabled
 	@DisplayName("should delete message")
 	@Test
 	@SneakyThrows
 	void shouldDeleteMessage() {
+		mockOperationsAndResponses(Map.of(
+				"deleteMessage", "200"
+		));
+
+		assertDoesNotThrow(() -> osiPostfachRemoteService.deleteMessage("00000000-0000-0000-0000-000000000000"));
+
+		// TODO verify delete message called
+		// var requests = postfachFacadeMockClient.retrieveRecordedRequests(request());
+	}
+
+	private void mockOperationsAndResponses(Map<String, String> operationsAndResponses) {
 		postfachFacadeMockClient.upsert(
 				openAPIExpectation()
-						.withSpecUrlOrPayload(Files.readString(Path.of("spec", "postfach-api-facade.yaml")))
-						.withOperationsAndResponses(Map.of(
-								"deleteMessage", "200"
-						))
+						.withSpecUrlOrPayload(getPostfachApiSpec())
+						.withOperationsAndResponses(operationsAndResponses)
 		);
-
-		assertDoesNotThrow(() -> osiPostfachRemoteService.deleteMessage("00000000-0000-0000-0000-000000000000"));
 	}
 
 }
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/JsonUtil.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/JsonUtil.java
index 5353606..ac01337 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/JsonUtil.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/JsonUtil.java
@@ -1,11 +1,13 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.factory;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 
 import lombok.SneakyThrows;
 
 public class JsonUtil {
-	private static final ObjectMapper jsonMapper = new ObjectMapper();
+	private static final ObjectMapper jsonMapper = new ObjectMapper()
+			.registerModule(new JavaTimeModule());
 
 	@SneakyThrows
 	public static String toJson(Object object) {
-- 
GitLab


From 69cb6a73c6357a562fb1031b26bd3f5d3d84fe07 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 24 Jan 2025 12:08:32 +0100
Subject: [PATCH 06/22] OZG-4095 config: Configure oauth2 manager

---
 .../osiv2/config/ApiClientConfiguration.java  | 168 +++++-------------
 .../extension/OsiMockServerExtension.java     |   2 +-
 2 files changed, 49 insertions(+), 121 deletions(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
index 650960e..d8671c1 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
@@ -1,6 +1,5 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.config;
 
-import jakarta.annotation.PostConstruct;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
@@ -10,21 +9,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
-import org.springframework.http.converter.FormHttpMessageConverter;
-import org.springframework.http.converter.json.JsonbHttpMessageConverter;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.oauth2.client.*;
-import org.springframework.security.oauth2.client.endpoint.*;
-import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
+import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
+import org.springframework.security.oauth2.client.endpoint.RestClientClientCredentialsTokenResponseClient;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
-import org.springframework.security.oauth2.client.registration.ClientRegistrations;
-import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
-import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
-import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
 import org.springframework.security.oauth2.client.web.client.OAuth2ClientHttpRequestInterceptor;
-import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestClient;
@@ -41,7 +34,6 @@ public class ApiClientConfiguration {
 
 	private final OsiPostfachProperties.ApiConfiguration apiConfiguration;
 	private final OsiPostfachProperties.ProxyConfiguration proxyConfiguration;
-	private static final String RESOURCE_HEADER = "resource";
 
 	@Bean
 	MessageExchangeApi messageExchangeApi(ApiClient apiClient) {
@@ -49,126 +41,31 @@ public class ApiClientConfiguration {
 	}
 
 	@Bean
-	ApiClient apiClient(OAuth2AuthorizedClientManager authorizedClientManager){
-		var apiClient = new ApiClient(restClient(authorizedClientManager));
+	ApiClient apiClient(RestClient restClient) {
+		var apiClient = new ApiClient(restClient);
 		apiClient.setBasePath(apiConfiguration.getUrl());
 		return apiClient;
 	}
 
-
 	@Bean
-	public RestClient restClient(OAuth2AuthorizedClientManager authorizedClientManager) {
+	public RestClient restClient(ClientRegistrationRepository clientRegistrations) {
 		OAuth2ClientHttpRequestInterceptor requestInterceptor =
-				new OAuth2ClientHttpRequestInterceptor(authorizedClientManager);
+				new OAuth2ClientHttpRequestInterceptor(authorizedClientManager(clientRegistrations));
+		requestInterceptor.setClientRegistrationIdResolver(request -> "osi2");
 
 		return RestClient.builder()
 				.requestInterceptor(requestInterceptor)
-				.
-
 				.build();
 	}
 
-
-
-	private  RestClient restClient;
-
-	@PostConstruct
-	void initialize() {
-
-		this.restClient = RestClient.builder()
-				.messageConverters((messageConverters) -> {
-					messageConverters.clear();
-					messageConverters.add(new FormHttpMessageConverter());
-//					messageConverters.add(new JsonbHttpMessageConverter());
-					messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
-				})
-				.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
-				// TODO: Customize the instance of RestClient as needed...
-				.build();
-	}
-
-	@Bean
-	public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() {
-		RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
-				new RestClientAuthorizationCodeTokenResponseClient();
-		accessTokenResponseClient.setRestClient(this.restClient);
-
-		return accessTokenResponseClient;
-	}
-
-	@Bean
-	public OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() {
-		RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
-				new RestClientRefreshTokenTokenResponseClient();
-		accessTokenResponseClient.setRestClient(this.restClient);
-
-		return accessTokenResponseClient;
-	}
-
-	@Bean
-	public OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() {
-		RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
-				new RestClientClientCredentialsTokenResponseClient();
-		accessTokenResponseClient.setRestClient(this.restClient);
-
-		return accessTokenResponseClient;
-	}
-
-	@Bean
-	public OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> passwordAccessTokenResponseClient() {
-		return (grantRequest) -> {
-			throw new UnsupportedOperationException("The `password` grant type is not supported.");
-		};
-	}
-
-	@Bean
-	public OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerAccessTokenResponseClient() {
-		RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
-				new RestClientJwtBearerTokenResponseClient();
-		accessTokenResponseClient.setRestClient(this.restClient);
-
-		return accessTokenResponseClient;
-	}
-
-	@Bean
-	public OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeAccessTokenResponseClient() {
-		RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
-				new RestClientTokenExchangeTokenResponseClient();
-		accessTokenResponseClient.setRestClient(this.restClient);
-
-		return accessTokenResponseClient;
-	}
-
-//	@Bean
-//	RestClient restClient(OAuth2AuthorizedClientManager authorizedClientManager) {
-//
-//		RestClient restClient = RestClient.builder()
-//				.requestFactory(createProxyRequestFactory())
-//				.requestInterceptor(createOAuth2Interceptor(authorizedClientManager))
-//				.baseUrl(apiConfiguration.getUrl())
-////				.defaultHeader(RESOURCE_HEADER, apiConfiguration.getResource())
-//				.build();
-//		return restClient;
-//	}
-
-//	@Bean
-//	public OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient(RestClient restClient) {
-//		RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
-//				new RestClientClientCredentialsTokenResponseClient();
-//		accessTokenResponseClient.setRestClient(restClient);
-//
-//		return accessTokenResponseClient;
-//	}
-
-
-	private ClientHttpRequestFactory createProxyRequestFactory(){
+	private ClientHttpRequestFactory createProxyRequestFactory() {
 		var requestFactory = new HttpComponentsClientHttpRequestFactory();
-		if(proxyConfiguration.isEnabled()){
+		if (proxyConfiguration.isEnabled()) {
 			var credsProvider = new BasicCredentialsProvider();
 			credsProvider.setCredentials(
 					new AuthScope(proxyConfiguration.getHost(), proxyConfiguration.getPort()),
-//TODO: hier brauchen wir noch eine Ordentliche Lösung
-//					new UsernamePasswordCredentials(proxyConfiguration.getUsername(), proxyConfiguration.getPassword().toCharArray())
+					//TODO: hier brauchen wir noch eine Ordentliche Lösung
+					//					new UsernamePasswordCredentials(proxyConfiguration.getUsername(), proxyConfiguration.getPassword().toCharArray())
 					new UsernamePasswordCredentials("", "".toCharArray())
 			);
 			var httpClient = HttpClientBuilder.create()
@@ -180,8 +77,39 @@ public class ApiClientConfiguration {
 		return requestFactory;
 	}
 
-	private ClientHttpRequestInterceptor createOAuth2Interceptor(OAuth2AuthorizedClientManager authorizedClientManager) {
-		var interceptor = new OAuth2ClientHttpRequestInterceptor(authorizedClientManager);
-		return interceptor;
+	private AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager(
+			ClientRegistrationRepository clientRegistrations) {
+		var clientService = new InMemoryOAuth2AuthorizedClientService(
+				clientRegistrations);
+		var authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(
+				clientRegistrations, clientService);
+
+		authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider());
+
+		return authorizedClientManager;
+	}
+
+	private OAuth2AuthorizedClientProvider authorizedClientProvider() {
+		return OAuth2AuthorizedClientProviderBuilder.builder()
+				.clientCredentials(builder ->
+						builder.accessTokenResponseClient(clientCredentialsTokenResponseClient())
+				)
+				.build();
 	}
+
+	private RestClientClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient() {
+		var client = new RestClientClientCredentialsTokenResponseClient();
+		configureParametersForTokenRequests(client);
+		return client;
+	}
+
+	private void configureParametersForTokenRequests(RestClientClientCredentialsTokenResponseClient client) {
+		client.addParametersConverter(source -> {
+			MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
+			// Pass a resource indicator parameter https://datatracker.ietf.org/doc/html/rfc8707
+			parameters.add("resource", apiConfiguration.getResource());
+			return parameters;
+		});
+	}
+
 }
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
index 5ce2169..9d59d95 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
@@ -105,7 +105,7 @@ public class OsiMockServerExtension implements BeforeAllCallback, AfterAllCallba
 								.withMethod("POST")
 								.withPath("/access-token")
 								.withHeaders(
-										header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
+										header("Content-Type", "application/x-www-form-urlencoded")
 								)
 								.withBody(
 										params(
-- 
GitLab


From b174e3f17761c9cecd616598114118b437e916b8 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 24 Jan 2025 12:50:14 +0100
Subject: [PATCH 07/22] OZG-4095 config: Configure proxy

---
 .../osiv2/config/ApiClientConfiguration.java  | 49 ++++++++++++++-----
 .../OsiPostfachRemoteServiceRemoteITCase.java |  4 +-
 2 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
index d8671c1..2cb4f19 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
@@ -10,14 +10,17 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.client.ClientHttpRequestFactory;
 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.FormHttpMessageConverter;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
 import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
 import org.springframework.security.oauth2.client.endpoint.RestClientClientCredentialsTokenResponseClient;
+import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.web.client.OAuth2ClientHttpRequestInterceptor;
+import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestClient;
@@ -53,30 +56,40 @@ public class ApiClientConfiguration {
 				new OAuth2ClientHttpRequestInterceptor(authorizedClientManager(clientRegistrations));
 		requestInterceptor.setClientRegistrationIdResolver(request -> "osi2");
 
-		return RestClient.builder()
+		return defaultRestClientBuilder()
 				.requestInterceptor(requestInterceptor)
 				.build();
 	}
 
+	private RestClient.Builder defaultRestClientBuilder() {
+		return RestClient.builder()
+				.requestFactory(createProxyRequestFactory());
+	}
+
 	private ClientHttpRequestFactory createProxyRequestFactory() {
 		var requestFactory = new HttpComponentsClientHttpRequestFactory();
 		if (proxyConfiguration.isEnabled()) {
-			var credsProvider = new BasicCredentialsProvider();
-			credsProvider.setCredentials(
-					new AuthScope(proxyConfiguration.getHost(), proxyConfiguration.getPort()),
-					//TODO: hier brauchen wir noch eine Ordentliche Lösung
-					//					new UsernamePasswordCredentials(proxyConfiguration.getUsername(), proxyConfiguration.getPassword().toCharArray())
-					new UsernamePasswordCredentials("", "".toCharArray())
+			requestFactory.setHttpClient(
+					HttpClientBuilder.create()
+							.setProxy(new HttpHost(proxyConfiguration.getHost(), proxyConfiguration.getPort()))
+							.setDefaultCredentialsProvider(basicCredentialsProviderForProxy())
+							.build()
 			);
-			var httpClient = HttpClientBuilder.create()
-					.setProxy(new HttpHost(proxyConfiguration.getHost(), proxyConfiguration.getPort()))
-					.setDefaultCredentialsProvider(credsProvider)
-					.build();
-			requestFactory.setHttpClient(httpClient);
 		}
 		return requestFactory;
 	}
 
+	private BasicCredentialsProvider basicCredentialsProviderForProxy() {
+		var credentialsProvider = new BasicCredentialsProvider();
+		var username = proxyConfiguration.getUsername();
+		var password = proxyConfiguration.getPassword();
+		if (username != null && password != null) {
+			credentialsProvider.setCredentials(new AuthScope(proxyConfiguration.getHost(), proxyConfiguration.getPort()),
+					new UsernamePasswordCredentials(username, password.toCharArray()));
+		}
+		return credentialsProvider;
+	}
+
 	private AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager(
 			ClientRegistrationRepository clientRegistrations) {
 		var clientService = new InMemoryOAuth2AuthorizedClientService(
@@ -99,10 +112,22 @@ public class ApiClientConfiguration {
 
 	private RestClientClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient() {
 		var client = new RestClientClientCredentialsTokenResponseClient();
+		configureClientCredentialsRestClient(client);
 		configureParametersForTokenRequests(client);
 		return client;
 	}
 
+	private void configureClientCredentialsRestClient(RestClientClientCredentialsTokenResponseClient client) {
+		client.setRestClient(defaultRestClientBuilder()
+				.messageConverters(messageConverters -> {
+					messageConverters.clear();
+					messageConverters.add(new FormHttpMessageConverter());
+					messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
+				})
+				.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
+				.build());
+	}
+
 	private void configureParametersForTokenRequests(RestClientClientCredentialsTokenResponseClient client) {
 		client.addParametersConverter(source -> {
 			MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
index 6012b3c..9978f98 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
@@ -83,8 +83,10 @@ public class OsiPostfachRemoteServiceRemoteITCase {
 		@Test
 		void shouldReceiveAllMessage(){
 			Stream<PostfachNachricht> allMessages = osiPostfachRemoteService.getAllMessages();
+
 			var messages = allMessages.toList();
-			assertThat(messages.size() > 0);
+
+			assertThat(messages).isNotEmpty();
 		}
 	}
 
-- 
GitLab


From d21d5fbeb2edaacd511d05f965753053730994ab Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 24 Jan 2025 13:32:41 +0100
Subject: [PATCH 08/22] OZG-4095 Avoid restClient bean

---
 .../postfach/osiv2/config/ApiClientConfiguration.java      | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
index 2cb4f19..729d574 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/ApiClientConfiguration.java
@@ -44,14 +44,13 @@ public class ApiClientConfiguration {
 	}
 
 	@Bean
-	ApiClient apiClient(RestClient restClient) {
-		var apiClient = new ApiClient(restClient);
+	ApiClient apiClient(ClientRegistrationRepository clientRegistrations) {
+		var apiClient = new ApiClient(restClient(clientRegistrations));
 		apiClient.setBasePath(apiConfiguration.getUrl());
 		return apiClient;
 	}
 
-	@Bean
-	public RestClient restClient(ClientRegistrationRepository clientRegistrations) {
+	private RestClient restClient(ClientRegistrationRepository clientRegistrations) {
 		OAuth2ClientHttpRequestInterceptor requestInterceptor =
 				new OAuth2ClientHttpRequestInterceptor(authorizedClientManager(clientRegistrations));
 		requestInterceptor.setClientRegistrationIdResolver(request -> "osi2");
-- 
GitLab


From f16bf35e6ea81e42baf9083f639a16ca32c46543 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 24 Jan 2025 15:34:24 +0100
Subject: [PATCH 09/22] OZG-4095 pom: Cleanup dependencies

---
 pom.xml                                       | 26 +++----------------
 .../factory/PostfachAddressTestFactory.java   |  2 ++
 2 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/pom.xml b/pom.xml
index ab38b51..8991d23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 	<parent>
 		<groupId>de.ozgcloud.common</groupId>
 		<artifactId>ozgcloud-common-parent</artifactId>
-		<version>4.9.0-SNAPSHOT</version>
+		<version>4.9.0</version>
 	</parent>
 
 	<groupId>de.ozgcloud.osiv2</groupId>
@@ -17,19 +17,14 @@
 	<description>OSIv2-Postfach-Anbindung für OZG-Cloud-Nachrichten</description>
 
 	<properties>
-		<api-lib.version>0.14.0</api-lib.version>
-		<nachrichten-manager.version>2.14.0</nachrichten-manager.version>
+		<api-lib.version>0.16.0</api-lib.version>
+		<nachrichten-manager.version>2.17.0-SNAPSHOT</nachrichten-manager.version>
 		<mockserver-client.version>5.15.0</mockserver-client.version>
 		<openapi-generator.version>7.10.0</openapi-generator.version>
 		<swagger-parser.version>2.1.23</swagger-parser.version>
 	</properties>
 	<dependencies>
 		<!-- OZG-Cloud -->
-		<dependency>
-			<groupId>de.ozgcloud.api-lib</groupId>
-			<artifactId>ozg-cloud-spring-boot-starter</artifactId>
-			<version>${api-lib.version}</version>
-		</dependency>
 		<dependency>
 			<groupId>de.ozgcloud.nachrichten</groupId>
 			<artifactId>nachrichten-manager-postfach-interface</artifactId>
@@ -48,21 +43,6 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-oauth2-client</artifactId>
 		</dependency>
-		<dependency>
-			<groupId>jakarta.servlet</groupId>
-			<artifactId>jakarta.servlet-api</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>jakarta.json.bind</groupId>
-			<artifactId>jakarta.json.bind-api</artifactId>
-			<version>3.0.1</version>
-		</dependency>
-		<dependency>
-			<groupId>org.eclipse</groupId>
-			<artifactId>yasson</artifactId>
-			<version>3.0.4</version>
-			<scope>test</scope>
-		</dependency>
 
 		<dependency>
 			<groupId>org.mapstruct</groupId>
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachAddressTestFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachAddressTestFactory.java
index a871295..046f298 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachAddressTestFactory.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachAddressTestFactory.java
@@ -5,6 +5,7 @@ import de.ozgcloud.nachrichten.postfach.PostfachAddress;
 public class PostfachAddressTestFactory {
 
 	public static final String MAILBOX_ID = "testMailboxId";
+	public static final String SERVICE_KONTO_TYPE = "TYPE1";
 
 	public static PostfachAddress create() {
 		return createBuilder().build();
@@ -13,6 +14,7 @@ public class PostfachAddressTestFactory {
 	public static PostfachAddress.PostfachAddressBuilder createBuilder() {
 		return PostfachAddress.builder()
 				.type(1)
+				.serviceKontoType("TYPE1")
 				.identifier(DummyStringBasedIdentifier.builder()
 						.mailboxId(MAILBOX_ID)
 						.build());
-- 
GitLab


From 27562f2ddd691cf386640155426c8d13f6c5feb7 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 27 Jan 2025 13:34:53 +0100
Subject: [PATCH 10/22] OZG-4095 config: Make nested classes public

---
 .../postfach/osiv2/config/Osi2PostfachProperties.java  | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
index 2cf55ad..f5a3d44 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
@@ -7,23 +7,29 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
 
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
 import lombok.Setter;
 
 @Getter
 @Setter
 @Configuration
 @ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
+@RequiredArgsConstructor
 public class Osi2PostfachProperties {
 
 	public static final String PREFIX = "ozgcloud.osiv2-postfach";
 
 	private boolean enabled;
 
+	private final ApiConfiguration api;
+
+	private final ProxyConfiguration httpProxy;
+
 	@Getter
 	@Setter
 	@Configuration
 	@ConfigurationProperties(prefix = ApiConfiguration.PREFIX)
-	static class ApiConfiguration {
+	public static class ApiConfiguration {
 		static final String PREFIX = Osi2PostfachProperties.PREFIX + ".api";
 
 		private String resource;
@@ -40,7 +46,7 @@ public class Osi2PostfachProperties {
 	@Setter
 	@Configuration
 	@ConfigurationProperties(prefix = ProxyConfiguration.PREFIX)
-	static class ProxyConfiguration {
+	public static class ProxyConfiguration {
 		static final String PREFIX = Osi2PostfachProperties.PREFIX + ".http-proxy";
 
 		private boolean enabled;
-- 
GitLab


From 70414f67cc1ebc9a39fc38730ca4886bbc04a952 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 27 Jan 2025 14:17:46 +0100
Subject: [PATCH 11/22] OZG-4095 config: Use `stage` profile

---
 pom.xml                                       |  7 ++++-
 src/main/resources/application-stage.yml      | 26 ++++++++++++++++++
 src/main/resources/application.yml            | 27 +------------------
 .../osiv2/OsiPostfachRemoteServiceITCase.java |  2 +-
 .../OsiPostfachRemoteServiceRemoteITCase.java | 10 +++----
 src/test/resources/application-itcase.yml     |  3 ---
 6 files changed, 39 insertions(+), 36 deletions(-)
 create mode 100644 src/main/resources/application-stage.yml

diff --git a/pom.xml b/pom.xml
index 8991d23..86abf55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
 
 	<groupId>de.ozgcloud.osiv2</groupId>
 	<artifactId>osiv2-postfach</artifactId>
-	<version>0.1.1-SNAPSHOT</version>
+	<version>0.1.0-SNAPSHOT</version>
 
 	<name>OZG-Cloud-OSIv2-Postfach</name>
 	<description>OSIv2-Postfach-Anbindung für OZG-Cloud-Nachrichten</description>
@@ -25,6 +25,11 @@
 	</properties>
 	<dependencies>
 		<!-- OZG-Cloud -->
+		<dependency>
+			<groupId>de.ozgcloud.api-lib</groupId>
+			<artifactId>ozg-cloud-spring-boot-starter</artifactId>
+			<version>${api-lib.version}</version>
+		</dependency>
 		<dependency>
 			<groupId>de.ozgcloud.nachrichten</groupId>
 			<artifactId>nachrichten-manager-postfach-interface</artifactId>
diff --git a/src/main/resources/application-stage.yml b/src/main/resources/application-stage.yml
new file mode 100644
index 0000000..f7c2e25
--- /dev/null
+++ b/src/main/resources/application-stage.yml
@@ -0,0 +1,26 @@
+spring:
+  security:
+    oauth2:
+      client:
+        registration:
+          osi2:
+            client-id: 'OZG-Kopfstelle'
+            client-secret: 'changeme'
+            scope: default, access_urn:dataport:osi:sh:stage:ozgkopfstelle
+            authorization-grant-type: 'client_credentials'
+            client-authentication-method: client_secret_post
+        provider:
+          osi2:
+            token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token'
+ozgcloud:
+  osiv2-postfach:
+    enabled: true
+    api:
+      resource: 'urn:dataport:osi:postfach:rz2:stage:sh'
+      url: 'https://api-gateway-stage.dataport.de:443/api/osi_postfach/1.0.0'
+      tenant: 'SH'
+      name-identifier: 'ozgkopfstelle'
+    http-proxy:
+      enabled: true
+      host: 127.0.0.1
+      port: 3128
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 1d1f1bf..065fffe 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,28 +1,3 @@
 spring:
   jackson:
-    default-property-inclusion: NON_NULL
-  security:
-    oauth2:
-      client:
-        registration:
-          osi2:
-            client-id: 'OZG-Kopfstelle'
-            client-secret: 'changeme'
-            scope: default, access_urn:dataport:osi:sh:stage:ozgkopfstelle
-            authorization-grant-type: 'client_credentials'
-            client-authentication-method: client_secret_post
-        provider:
-          osi2:
-            token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token'
-ozgcloud:
-  osiv2-postfach:
-    enabled: false
-    api:
-      resource: 'urn:dataport:osi:postfach:rz2:stage:sh'
-      url: 'https://api-gateway-stage.dataport.de:443/api/osi_postfach/1.0.0'
-      tenant: 'SH'
-      name-identifier: 'ozgkopfstelle'
-    http-proxy:
-      enabled: true
-      host: 127.0.0.1
-      port: 3128
+    default-property-inclusion: NON_NULL
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
index 2771bbd..dcfa4c5 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -38,7 +38,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMe
 import lombok.SneakyThrows;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles("itcase")
+@ActiveProfiles({"itcase", "stage"})
 @TestPropertySource(properties = {
 		"ozgcloud.osiv2-postfach.http-proxy.enabled=false",
 })
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
index 9978f98..9301a37 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
@@ -23,7 +23,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles("local")
+@ActiveProfiles({ "local", "stage" })
 @EnabledIfEnvironmentVariable(named = "SH_STAGE_CLIENT_SECRET", matches = ".+")
 public class OsiPostfachRemoteServiceRemoteITCase {
 
@@ -78,10 +78,10 @@ public class OsiPostfachRemoteServiceRemoteITCase {
 
 	@DisplayName("receive all messages")
 	@Nested
-	class TestReceiveAllMessages{
+	class TestReceiveAllMessages {
 
 		@Test
-		void shouldReceiveAllMessage(){
+		void shouldReceiveAllMessage() {
 			Stream<PostfachNachricht> allMessages = osiPostfachRemoteService.getAllMessages();
 
 			var messages = allMessages.toList();
@@ -93,10 +93,10 @@ public class OsiPostfachRemoteServiceRemoteITCase {
 	@Disabled
 	@DisplayName("delete message")
 	@Nested
-	class TestDeleteMessageById{
+	class TestDeleteMessageById {
 
 		@Test
-		void shouldDeleteMessage(){
+		void shouldDeleteMessage() {
 			assertThatCode(() -> osiPostfachRemoteService.deleteMessage("5dd65c1e-bd41-4c3d-bf98-be769ca341dc"))
 					.doesNotThrowAnyException();
 		}
diff --git a/src/test/resources/application-itcase.yml b/src/test/resources/application-itcase.yml
index d8cacf7..dcbea65 100644
--- a/src/test/resources/application-itcase.yml
+++ b/src/test/resources/application-itcase.yml
@@ -1,6 +1,3 @@
-ozgcloud:
-  osiv2-postfach:
-    enabled: true
 logging:
   level:
     de.ozgcloud.nachrichten.postfach.osiv2: DEBUG
-- 
GitLab


From 05642db428f2cf77890be0742070f6b6f5defcfc Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 27 Jan 2025 14:22:40 +0100
Subject: [PATCH 12/22] OZG-4095 config: Disable osi2.enable by default for
 `stage`

---
 src/main/resources/application-stage.yml  | 2 +-
 src/test/resources/application-itcase.yml | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/main/resources/application-stage.yml b/src/main/resources/application-stage.yml
index f7c2e25..6892480 100644
--- a/src/main/resources/application-stage.yml
+++ b/src/main/resources/application-stage.yml
@@ -14,7 +14,7 @@ spring:
             token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token'
 ozgcloud:
   osiv2-postfach:
-    enabled: true
+    enabled: false
     api:
       resource: 'urn:dataport:osi:postfach:rz2:stage:sh'
       url: 'https://api-gateway-stage.dataport.de:443/api/osi_postfach/1.0.0'
diff --git a/src/test/resources/application-itcase.yml b/src/test/resources/application-itcase.yml
index dcbea65..d8cacf7 100644
--- a/src/test/resources/application-itcase.yml
+++ b/src/test/resources/application-itcase.yml
@@ -1,3 +1,6 @@
+ozgcloud:
+  osiv2-postfach:
+    enabled: true
 logging:
   level:
     de.ozgcloud.nachrichten.postfach.osiv2: DEBUG
-- 
GitLab


From 1315be523c106fac6c13e719cbbc23bea74e9397 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 27 Jan 2025 14:27:10 +0100
Subject: [PATCH 13/22] OZG-4095 config: Disable osi2.enable by default for
 `stage`

---
 .../postfach/osiv2/OsiPostfachRemoteServiceITCase.java          | 2 +-
 .../postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
index dcfa4c5..f75663d 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -38,7 +38,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMe
 import lombok.SneakyThrows;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles({"itcase", "stage"})
+@ActiveProfiles({"stage", "itcase"})
 @TestPropertySource(properties = {
 		"ozgcloud.osiv2-postfach.http-proxy.enabled=false",
 })
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
index 9301a37..27c5c05 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
@@ -23,7 +23,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles({ "local", "stage" })
+@ActiveProfiles({ "stage", "local" })
 @EnabledIfEnvironmentVariable(named = "SH_STAGE_CLIENT_SECRET", matches = ".+")
 public class OsiPostfachRemoteServiceRemoteITCase {
 
-- 
GitLab


From a9101e0f7668f7ced265d6a314aaa681acde2b78 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 27 Jan 2025 17:07:18 +0100
Subject: [PATCH 14/22] OZG-4095 wiremock: Replace mockserver with wiremock

---
 pom.xml                                       |   8 ++
 .../osiv2/OsiPostfachRemoteServiceITCase.java | 112 ++++++++++--------
 .../extension/OsiMockServerExtension.java     | 101 +++-------------
 3 files changed, 88 insertions(+), 133 deletions(-)

diff --git a/pom.xml b/pom.xml
index 86abf55..1e8f3fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,6 +22,7 @@
 		<mockserver-client.version>5.15.0</mockserver-client.version>
 		<openapi-generator.version>7.10.0</openapi-generator.version>
 		<swagger-parser.version>2.1.23</swagger-parser.version>
+		<wiremock-spring-boot.version>3.6.0</wiremock-spring-boot.version>
 	</properties>
 	<dependencies>
 		<!-- OZG-Cloud -->
@@ -86,6 +87,13 @@
 			<scope>test</scope>
 		</dependency>
 
+		<dependency>
+			<groupId>org.wiremock.integrations</groupId>
+			<artifactId>wiremock-spring-boot</artifactId>
+			<version>${wiremock-spring-boot.version}</version>
+		</dependency>
+
+
 		<!-- commons -->
 		<dependency>
 			<groupId>org.apache.commons</groupId>
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
index f75663d..d20919e 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -1,25 +1,19 @@
 package de.ozgcloud.nachrichten.postfach.osiv2;
 
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
 import static de.ozgcloud.nachrichten.postfach.osiv2.factory.JwtFactory.*;
 import static org.assertj.core.api.Assertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockserver.mock.OpenAPIExpectation.*;
-import static org.mockserver.model.HttpRequest.*;
-import static org.mockserver.model.HttpResponse.*;
 
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.time.OffsetDateTime;
 import java.util.Arrays;
-import java.util.Map;
 import java.util.UUID;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
-import org.mockserver.client.MockServerClient;
-import org.mockserver.model.OpenAPIDefinition;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.ActiveProfiles;
@@ -27,6 +21,9 @@ import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
 import org.springframework.test.context.TestPropertySource;
 
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
+
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.extension.Jwt;
 import de.ozgcloud.nachrichten.postfach.osiv2.extension.OsiMockServerExtension;
@@ -35,10 +32,11 @@ import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFacto
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageFactory;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessagesResponse;
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeSendMessageResponse;
 import lombok.SneakyThrows;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles({"stage", "itcase"})
+@ActiveProfiles({ "stage", "itcase" })
 @TestPropertySource(properties = {
 		"ozgcloud.osiv2-postfach.http-proxy.enabled=false",
 })
@@ -66,29 +64,40 @@ class OsiPostfachRemoteServiceITCase {
 		registry.add("ozgcloud.osiv2-postfach.api.resource", () -> RESOURCE_URN);
 	}
 
-	private MockServerClient postfachFacadeMockClient;
+	private WireMockServer postfachFacadeMockServer;
+	private WireMockServer serviceKontoMockServer;
 
 	@BeforeEach
 	@SneakyThrows
 	public void setup() {
-		postfachFacadeMockClient = OSI_MOCK_SERVER_EXTENSION.getPostfachFacadeMockClient();
+		postfachFacadeMockServer = OSI_MOCK_SERVER_EXTENSION.getPostfachFacadeMockServer();
+		serviceKontoMockServer = OSI_MOCK_SERVER_EXTENSION.getServiceKontoMockServer();
 	}
 
 	@DisplayName("should send request with jwt")
 	@Test
 	@SneakyThrows
 	void shouldSendRequestWithJwt() {
-		mockOperationsAndResponses(Map.of(
-				"SendMessage", "200"
-		));
+		// Stub message send response (MessageExchangeApi::sendMessage)
+		postfachFacadeMockServer.stubFor(post("/MessageExchange/v1/Send/{mailboxId}")
+				.willReturn(okJsonObj(new MessageExchangeSendMessageResponse().messageId(UUID.randomUUID())))
+		);
 
 		osiPostfachRemoteService.sendMessage(postfachNachricht);
 
-		var requests = postfachFacadeMockClient.retrieveRecordedRequests(request());
-		assertThat(requests).hasSize(1);
-		var jwt = Jwt.parseAuthHeaderValue(
-				requests[0].getHeader("Authorization").getFirst()
+		serviceKontoMockServer.verify(
+				exactly(1),
+				postRequestedFor(urlEqualTo(OSI_MOCK_SERVER_EXTENSION.getAccessTokenUrl()))
+						.withHeader("Content-Type", equalTo("application/x-www-form-urlencoded"))
+						.withQueryParam("grant_type", equalTo("client_credentials"))
+						.withQueryParam("client_id", equalTo(CLIENT_ID))
+						.withQueryParam("scope", equalTo(String.join(" ", CLIENT_SCOPES)))
+						.withQueryParam("resource", equalTo(RESOURCE_URN))
 		);
+		var requests = postfachFacadeMockServer.findAll(
+				postRequestedFor(urlPathEqualTo("/MessageExchange/v1/Send")));
+		assertThat(requests).hasSize(1);
+		var jwt = Jwt.parseAuthHeaderValue(requests.getFirst().getHeader("Authorization"));
 		assertThat(jwt.body().read("$.client_id", String.class)).isEqualTo(CLIENT_ID);
 		assertThat(jwt.body().read("$.aud", String.class)).isEqualTo(RESOURCE_URN);
 	}
@@ -116,53 +125,54 @@ class OsiPostfachRemoteServiceITCase {
 	}
 
 	private void mockPostfachMessageAndResponse(final String... uuids) {
-		// Stub message listing response
-		mockJsonOperation("receiveMessages", new MessageExchangeReceiveMessagesResponse()
-				.messages(Arrays.stream(uuids)
-						.map(uuid -> new MessageExchangeReceiveMessage()
-								.guid(UUID.fromString(uuid)))
-						.toList()));
+		// Stub message listing response (MessageExchangeApi::receiveMessages)
+		postfachFacadeMockServer.stubFor(get("/MessageExchange/v1/Receive")
+				.willReturn(
+						okJsonObj(
+								new MessageExchangeReceiveMessagesResponse()
+										.messages(Arrays.stream(uuids)
+												.map(uuid -> new MessageExchangeReceiveMessage()
+														.guid(UUID.fromString(uuid)))
+												.toList())
+						)
+				)
+		);
 		for (String uuid : uuids) {
-			// Stub individual response for message
-			mockJsonOperation("getMessage", V1ReplyMessageFactory.create()
-					.messageBox(UUID.fromString(uuid))
-					.responseTime(OffsetDateTime.now()));
+			// Stub individual response for message (MessageExchangeApi::getMessage)
+			postfachFacadeMockServer.stubFor(get("/MessageExchange/v1/Receive/{messageId}")
+					.withPathParam("messageId", equalTo(uuid))
+					.willReturn(
+							okJsonObj(
+									V1ReplyMessageFactory.create()
+											.messageBox(UUID.fromString(uuid))
+											.responseTime(OffsetDateTime.now())
+							)
+					)
+			);
 		}
 	}
 
-	private void mockJsonOperation(final String operationId, final Object body) {
-		postfachFacadeMockClient
-				.when(
-						new OpenAPIDefinition()
-								.withSpecUrlOrPayload(getPostfachApiSpec())
-								.withOperationId(operationId)
-				)
-				.respond(
-						response()
-								.withHeader("Content-type", "application/json")
-								.withBody(JsonUtil.toJson(body))
-				);
+	private ResponseDefinitionBuilder okJsonObj(final Object body) {
+		return okJson(JsonUtil.toJson(body));
 	}
 
 	@DisplayName("should delete message")
 	@Test
 	@SneakyThrows
 	void shouldDeleteMessage() {
-		mockOperationsAndResponses(Map.of(
-				"deleteMessage", "200"
-		));
+		var messageId = "00000000-0000-0000-0000-000000000000";
+		// Stub delete message response (MessageExchangeApi::deleteMessage)
+		postfachFacadeMockServer.stubFor(delete("/MessageExchange/v1/Delete/{messageId}")
+				.willReturn(ok())
+		);
 
-		assertDoesNotThrow(() -> osiPostfachRemoteService.deleteMessage("00000000-0000-0000-0000-000000000000"));
+		osiPostfachRemoteService.deleteMessage(messageId);
 
-		// TODO verify delete message called
-		// var requests = postfachFacadeMockClient.retrieveRecordedRequests(request());
-	}
 
-	private void mockOperationsAndResponses(Map<String, String> operationsAndResponses) {
-		postfachFacadeMockClient.upsert(
-				openAPIExpectation()
-						.withSpecUrlOrPayload(getPostfachApiSpec())
-						.withOperationsAndResponses(operationsAndResponses)
+		postfachFacadeMockServer.verify(
+				exactly(1),
+				deleteRequestedFor(urlPathEqualTo("/MessageExchange/v1/Delete/{messageId}"))
+						.withPathParam("messageId", equalTo(messageId))
 		);
 	}
 
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
index 9d59d95..adf3e29 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
@@ -1,22 +1,14 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.extension;
 
-import static de.ozgcloud.nachrichten.postfach.osiv2.factory.JwtFactory.*;
-import static org.mockserver.matchers.Times.*;
-import static org.mockserver.model.Header.*;
-import static org.mockserver.model.HttpRequest.*;
-import static org.mockserver.model.HttpResponse.*;
-import static org.mockserver.model.Parameter.*;
-import static org.mockserver.model.ParameterBody.*;
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
 
 import org.junit.jupiter.api.extension.AfterAllCallback;
 import org.junit.jupiter.api.extension.AfterEachCallback;
 import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
-import org.mockserver.client.MockServerClient;
-import org.testcontainers.containers.MockServerContainer;
-import org.testcontainers.containers.output.OutputFrame;
-import org.testcontainers.utility.DockerImageName;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.JwtFactory;
 import lombok.Getter;
@@ -28,25 +20,8 @@ import lombok.extern.log4j.Log4j2;
 @RequiredArgsConstructor
 public class OsiMockServerExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback {
 
-	private MockServerClient serviceKontoMockClient;
-	private MockServerClient postfachFacadeMockClient;
-
-	private static final DockerImageName MOCK_SERVER_IMAGE = DockerImageName.parse("mockserver/mockserver")
-			.withTag("mockserver-5.15.0");
-
-	private final MockServerContainer serviceKontoMockContainer = new MockServerContainer(MOCK_SERVER_IMAGE)
-			.withLogConsumer(this::logContainerOutput);
-	private final MockServerContainer postfachFacadeMockContainer = new MockServerContainer(MOCK_SERVER_IMAGE)
-			.withLogConsumer(this::logContainerOutput);
-
-	private void logContainerOutput(OutputFrame outputFrame) {
-		var line = outputFrame.getUtf8String().stripTrailing();
-		if (outputFrame.getType() == OutputFrame.OutputType.STDERR) {
-			System.err.println(line);
-		} else {
-			System.out.println(line);
-		}
-	}
+	private WireMockServer serviceKontoMockServer;
+	private WireMockServer postfachFacadeMockServer;
 
 	@Override
 	public void beforeAll(ExtensionContext context) {
@@ -56,77 +31,39 @@ public class OsiMockServerExtension implements BeforeAllCallback, AfterAllCallba
 
 	@Override
 	public void afterEach(ExtensionContext context) {
-		postfachFacadeMockClient.reset();
-		serviceKontoMockClient.reset();
+		postfachFacadeMockServer.resetAll();
+		serviceKontoMockServer.resetAll();
 	}
 
 	@Override
 	public void afterAll(ExtensionContext context) {
-		serviceKontoMockClient.stop();
-		serviceKontoMockContainer.stop();
-
-		postfachFacadeMockClient.stop();
-		postfachFacadeMockContainer.stop();
+		serviceKontoMockServer.shutdown();
+		postfachFacadeMockServer.shutdown();
 	}
 
 	private void setupPostfachFacadeMock() {
-		postfachFacadeMockContainer.start();
-		postfachFacadeMockClient = new MockServerClient(
-				postfachFacadeMockContainer.getHost(),
-				postfachFacadeMockContainer.getServerPort()
-		);
+		postfachFacadeMockServer = new WireMockServer(0);
+		postfachFacadeMockServer.start();
 	}
 
 	private void setupServiceKontoMock() {
-		serviceKontoMockContainer.start();
-		serviceKontoMockClient = new MockServerClient(
-				serviceKontoMockContainer.getHost(),
-				serviceKontoMockContainer.getServerPort()
-		);
+		serviceKontoMockServer = new WireMockServer(0);
+		serviceKontoMockServer.start();
 	}
 
 	public String getAccessTokenUrl() {
-		return getMockServerUrl(serviceKontoMockClient) + "/access-token";
+		return serviceKontoMockServer.baseUrl() + "/access-token";
 	}
 
 	public String getPostfachFacadeUrl() {
-		return getMockServerUrl(postfachFacadeMockClient);
-	}
-
-	private String getMockServerUrl(MockServerClient mockClient) {
-		return "http://" + mockClient.remoteAddress().getHostName() + ":" + mockClient.remoteAddress().getPort();
+		return postfachFacadeMockServer.baseUrl();
 	}
 
 	@Override
 	public void beforeEach(ExtensionContext context) {
-		serviceKontoMockClient
-				.when(
-						request()
-								.withMethod("POST")
-								.withPath("/access-token")
-								.withHeaders(
-										header("Content-Type", "application/x-www-form-urlencoded")
-								)
-								.withBody(
-										params(
-												param("grant_type", "client_credentials"),
-												param("client_id", CLIENT_ID),
-												param("client_secret", "changeme"),
-												param("scope", String.join(" ", CLIENT_SCOPES)),
-												param("resource", RESOURCE_URN)
-										)
-								),
-						exactly(1)
-				)
-				.respond(
-						response()
-								.withStatusCode(200)
-								.withHeader("Content-Type", "application/json")
-								.withBody(
-										JwtFactory.createTokenResponse(
-												JwtFactory.createAccessTokenExampleWithExpireIn(900)
-										)
-								)
-				);
+		serviceKontoMockServer.stubFor(post("/access-token")
+				.willReturn(okJson(JwtFactory.createTokenResponse(
+						JwtFactory.createAccessTokenExampleWithExpireIn(900)
+				))));
 	}
 }
-- 
GitLab


From 88f2c78163f0f13a0a0afd29d7ca1155b25f0f35 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 27 Jan 2025 17:10:14 +0100
Subject: [PATCH 15/22] OZG-4095 todo: Add nullable reminder

---
 .../postfach/osiv2/transfer/PostfachApiFacadeService.java      | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
index 7f62892..ed46e27 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
@@ -23,7 +23,7 @@ public class PostfachApiFacadeService {
 	private final RequestMapper requestMapper;
 	private final  ResponseMapper responseMapper;
 
-	private static int MAX_NUMBER_RECEIVED_MESSAGES = 100;
+	private static final int MAX_NUMBER_RECEIVED_MESSAGES = 100;
 
 	public void sendMessage(PostfachNachricht nachricht) {
 		messageExchangeApi.sendMessage(
@@ -34,6 +34,7 @@ public class PostfachApiFacadeService {
 
 	public Stream<PostfachNachricht> receiveMessages() {
 		var response = messageExchangeApi.receiveMessages(MAX_NUMBER_RECEIVED_MESSAGES, 0);
+		// TODO response.getMessages() is Nullable
 		return response.getMessages().stream().map(this::fetchMessageByGuid);
 	}
 
-- 
GitLab


From 4387d35529add50fb62479262998461d192157d4 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Tue, 28 Jan 2025 12:12:45 +0100
Subject: [PATCH 16/22] OZG-4095 wiremock: Adjust factories and matching

---
 .../osiv2/OsiPostfachRemoteServiceITCase.java | 54 ++++++++-----------
 .../extension/OsiMockServerExtension.java     |  6 +++
 ...sageExchangeReceiveMessageTestFactory.java | 15 ++++++
 ...ngeReceiveMessagesResponseTestFactory.java | 13 +++++
 ...xchangeSendMessageResponseTestFactory.java | 13 +++++
 ...ry.java => V1ReplyMessageTestFactory.java} | 28 +++++-----
 .../osiv2/transfer/ResponseMapperTest.java    |  4 +-
 7 files changed, 84 insertions(+), 49 deletions(-)
 create mode 100644 src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessageTestFactory.java
 create mode 100644 src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessagesResponseTestFactory.java
 create mode 100644 src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeSendMessageResponseTestFactory.java
 rename src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/{V1ReplyMessageFactory.java => V1ReplyMessageTestFactory.java} (51%)

diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
index d20919e..1de65de 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -4,8 +4,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.*;
 import static de.ozgcloud.nachrichten.postfach.osiv2.factory.JwtFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
-import java.nio.file.Files;
-import java.nio.file.Path;
 import java.time.OffsetDateTime;
 import java.util.Arrays;
 import java.util.UUID;
@@ -28,11 +26,11 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.extension.Jwt;
 import de.ozgcloud.nachrichten.postfach.osiv2.extension.OsiMockServerExtension;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.JsonUtil;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.MessageExchangeReceiveMessageTestFactory;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.MessageExchangeReceiveMessagesResponseTestFactory;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.MessageExchangeSendMessageResponseTestFactory;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
-import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageFactory;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessagesResponse;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeSendMessageResponse;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageTestFactory;
 import lombok.SneakyThrows;
 
 @SpringBootTest(classes = TestApplication.class)
@@ -45,11 +43,6 @@ class OsiPostfachRemoteServiceITCase {
 	@RegisterExtension
 	static final OsiMockServerExtension OSI_MOCK_SERVER_EXTENSION = new OsiMockServerExtension();
 
-	@SneakyThrows
-	private static String getPostfachApiSpec() {
-		return Files.readString(Path.of("spec", "postfach-api-facade.yaml"));
-	}
-
 	private final PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create();
 
 	@Autowired
@@ -65,13 +58,11 @@ class OsiPostfachRemoteServiceITCase {
 	}
 
 	private WireMockServer postfachFacadeMockServer;
-	private WireMockServer serviceKontoMockServer;
 
 	@BeforeEach
 	@SneakyThrows
 	public void setup() {
 		postfachFacadeMockServer = OSI_MOCK_SERVER_EXTENSION.getPostfachFacadeMockServer();
-		serviceKontoMockServer = OSI_MOCK_SERVER_EXTENSION.getServiceKontoMockServer();
 	}
 
 	@DisplayName("should send request with jwt")
@@ -79,23 +70,19 @@ class OsiPostfachRemoteServiceITCase {
 	@SneakyThrows
 	void shouldSendRequestWithJwt() {
 		// Stub message send response (MessageExchangeApi::sendMessage)
-		postfachFacadeMockServer.stubFor(post("/MessageExchange/v1/Send/{mailboxId}")
-				.willReturn(okJsonObj(new MessageExchangeSendMessageResponse().messageId(UUID.randomUUID())))
+		postfachFacadeMockServer.stubFor(post(urlPathTemplate("/MessageExchange/v1/Send/{mailboxId}"))
+				.willReturn(
+						okJsonObj(
+								MessageExchangeSendMessageResponseTestFactory.create()
+										.messageId(UUID.randomUUID())
+						)
+				)
 		);
 
 		osiPostfachRemoteService.sendMessage(postfachNachricht);
 
-		serviceKontoMockServer.verify(
-				exactly(1),
-				postRequestedFor(urlEqualTo(OSI_MOCK_SERVER_EXTENSION.getAccessTokenUrl()))
-						.withHeader("Content-Type", equalTo("application/x-www-form-urlencoded"))
-						.withQueryParam("grant_type", equalTo("client_credentials"))
-						.withQueryParam("client_id", equalTo(CLIENT_ID))
-						.withQueryParam("scope", equalTo(String.join(" ", CLIENT_SCOPES)))
-						.withQueryParam("resource", equalTo(RESOURCE_URN))
-		);
 		var requests = postfachFacadeMockServer.findAll(
-				postRequestedFor(urlPathEqualTo("/MessageExchange/v1/Send")));
+				postRequestedFor(urlPathTemplate("/MessageExchange/v1/Send/{mailboxId}")));
 		assertThat(requests).hasSize(1);
 		var jwt = Jwt.parseAuthHeaderValue(requests.getFirst().getHeader("Authorization"));
 		assertThat(jwt.body().read("$.client_id", String.class)).isEqualTo(CLIENT_ID);
@@ -126,12 +113,14 @@ class OsiPostfachRemoteServiceITCase {
 
 	private void mockPostfachMessageAndResponse(final String... uuids) {
 		// Stub message listing response (MessageExchangeApi::receiveMessages)
-		postfachFacadeMockServer.stubFor(get("/MessageExchange/v1/Receive")
+		postfachFacadeMockServer.stubFor(get(urlPathEqualTo("/MessageExchange/v1/Receive"))
+				.withQueryParam("take", equalTo("100"))
+				.withQueryParam("skip", equalTo("0"))
 				.willReturn(
 						okJsonObj(
-								new MessageExchangeReceiveMessagesResponse()
+								MessageExchangeReceiveMessagesResponseTestFactory.create()
 										.messages(Arrays.stream(uuids)
-												.map(uuid -> new MessageExchangeReceiveMessage()
+												.map(uuid -> MessageExchangeReceiveMessageTestFactory.create()
 														.guid(UUID.fromString(uuid)))
 												.toList())
 						)
@@ -139,11 +128,11 @@ class OsiPostfachRemoteServiceITCase {
 		);
 		for (String uuid : uuids) {
 			// Stub individual response for message (MessageExchangeApi::getMessage)
-			postfachFacadeMockServer.stubFor(get("/MessageExchange/v1/Receive/{messageId}")
+			postfachFacadeMockServer.stubFor(get(urlPathTemplate("/MessageExchange/v1/Receive/{messageId}"))
 					.withPathParam("messageId", equalTo(uuid))
 					.willReturn(
 							okJsonObj(
-									V1ReplyMessageFactory.create()
+									V1ReplyMessageTestFactory.create()
 											.messageBox(UUID.fromString(uuid))
 											.responseTime(OffsetDateTime.now())
 							)
@@ -162,16 +151,15 @@ class OsiPostfachRemoteServiceITCase {
 	void shouldDeleteMessage() {
 		var messageId = "00000000-0000-0000-0000-000000000000";
 		// Stub delete message response (MessageExchangeApi::deleteMessage)
-		postfachFacadeMockServer.stubFor(delete("/MessageExchange/v1/Delete/{messageId}")
+		postfachFacadeMockServer.stubFor(delete(urlPathTemplate("/MessageExchange/v1/Delete/{messageId}"))
 				.willReturn(ok())
 		);
 
 		osiPostfachRemoteService.deleteMessage(messageId);
 
-
 		postfachFacadeMockServer.verify(
 				exactly(1),
-				deleteRequestedFor(urlPathEqualTo("/MessageExchange/v1/Delete/{messageId}"))
+				deleteRequestedFor(urlPathTemplate("/MessageExchange/v1/Delete/{messageId}"))
 						.withPathParam("messageId", equalTo(messageId))
 		);
 	}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
index adf3e29..71cd29c 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/OsiMockServerExtension.java
@@ -1,6 +1,7 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.extension;
 
 import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static de.ozgcloud.nachrichten.postfach.osiv2.factory.JwtFactory.*;
 
 import org.junit.jupiter.api.extension.AfterAllCallback;
 import org.junit.jupiter.api.extension.AfterEachCallback;
@@ -62,6 +63,11 @@ public class OsiMockServerExtension implements BeforeAllCallback, AfterAllCallba
 	@Override
 	public void beforeEach(ExtensionContext context) {
 		serviceKontoMockServer.stubFor(post("/access-token")
+				.withHeader("Content-Type", equalTo("application/x-www-form-urlencoded"))
+				.withFormParam("grant_type", equalTo("client_credentials"))
+				.withFormParam("client_id", equalTo(CLIENT_ID))
+				.withFormParam("scope", equalTo(String.join(" ", CLIENT_SCOPES)))
+				.withFormParam("resource", equalTo(RESOURCE_URN))
 				.willReturn(okJson(JwtFactory.createTokenResponse(
 						JwtFactory.createAccessTokenExampleWithExpireIn(900)
 				))));
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessageTestFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessageTestFactory.java
new file mode 100644
index 0000000..75a60a2
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessageTestFactory.java
@@ -0,0 +1,15 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.factory;
+
+import java.util.UUID;
+
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
+
+public class MessageExchangeReceiveMessageTestFactory {
+
+	public static final UUID MESSAGE_ID = UUID.randomUUID();
+
+	public static MessageExchangeReceiveMessage create() {
+		return new MessageExchangeReceiveMessage()
+				.guid(MESSAGE_ID);
+	}
+}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessagesResponseTestFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessagesResponseTestFactory.java
new file mode 100644
index 0000000..8721bbb
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeReceiveMessagesResponseTestFactory.java
@@ -0,0 +1,13 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.factory;
+
+import java.util.List;
+
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessagesResponse;
+
+public class MessageExchangeReceiveMessagesResponseTestFactory {
+
+	public static MessageExchangeReceiveMessagesResponse create() {
+		return new MessageExchangeReceiveMessagesResponse()
+				.messages(List.of());
+	}
+}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeSendMessageResponseTestFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeSendMessageResponseTestFactory.java
new file mode 100644
index 0000000..0c296a6
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/MessageExchangeSendMessageResponseTestFactory.java
@@ -0,0 +1,13 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.factory;
+
+import static de.ozgcloud.nachrichten.postfach.osiv2.factory.MessageExchangeReceiveMessageTestFactory.*;
+
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeSendMessageResponse;
+
+public class MessageExchangeSendMessageResponseTestFactory {
+
+	public static MessageExchangeSendMessageResponse create() {
+		return new MessageExchangeSendMessageResponse()
+				.messageId(MESSAGE_ID);
+	}
+}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/V1ReplyMessageFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/V1ReplyMessageTestFactory.java
similarity index 51%
rename from src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/V1ReplyMessageFactory.java
rename to src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/V1ReplyMessageTestFactory.java
index 61a52ac..244a643 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/V1ReplyMessageFactory.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/V1ReplyMessageTestFactory.java
@@ -7,22 +7,22 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1EidasLevel;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyMessage;
 
-public class V1ReplyMessageFactory {
+public class V1ReplyMessageTestFactory {
 
-	private static String SEQUENCE_NUMMER = "OZG-Cloud-VorgangId";
-	private static String SUBJECT = "Das ist das Subject";
-	private static String BODY = """
+	private static final String SEQUENCE_NUMMER = "OZG-Cloud-VorgangId";
+	private static final String SUBJECT = "Das ist das Subject";
+	private static final String BODY = """
 			Das ist das Multiline
 			Body""";
-	private static String DISPLAY_NAME = "Das ist der Absender";
-	private static String ORIGIN_SENDER = "das ist der original Sender";
-	private static String REPLAY_ACTION = "Replypossible";
-	private static String EIDAS_LEVEL = "Low";
-	private static Boolean IS_OLIGATORY = Boolean.FALSE;
-	private static Boolean IS_HTML = Boolean.FALSE;
-	private static String GUID = "123-guid-456";
-	private static String MESSAGE_BOX = "Mailbox-Id-Antwortender";
-	private static OffsetDateTime RESPONSE_TIME = OffsetDateTime.now();
+	private static final String DISPLAY_NAME = "Das ist der Absender";
+	private static final String ORIGIN_SENDER = "das ist der original Sender";
+	private static final String REPLAY_ACTION = "Replypossible";
+	private static final String EIDAS_LEVEL = "Low";
+	private static final Boolean IS_OBLIGATORY = Boolean.FALSE;
+	private static final Boolean IS_HTML = Boolean.FALSE;
+	private static final String GUID = "123-guid-456";
+	private static final String MESSAGE_BOX = "Mailbox-Id-Antwortender";
+	private static final OffsetDateTime RESPONSE_TIME = OffsetDateTime.now();
 
 	public static V1ReplyMessage create() {
 		return new V1ReplyMessage()
@@ -33,7 +33,7 @@ public class V1ReplyMessageFactory {
 				.originSender(ORIGIN_SENDER)
 				.replyAction(V1ReplyBehavior.fromValue(REPLAY_ACTION))
 				.eidasLevel(V1EidasLevel.fromValue(EIDAS_LEVEL))
-				.isObligatory(IS_OLIGATORY)
+				.isObligatory(IS_OBLIGATORY)
 				.isHtml(IS_HTML)
 				.guid(UUID.nameUUIDFromBytes(GUID.getBytes()))
 				.messageBox(UUID.nameUUIDFromBytes(MESSAGE_BOX.getBytes()))
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java
index d4c8706..c45f08e 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java
@@ -13,14 +13,14 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
-import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageFactory;
+import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageTestFactory;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyMessage;
 
 class ResponseMapperTest {
 
 	@InjectMocks
 	private ResponseMapper mapper = Mappers.getMapper(ResponseMapper.class);
-	private V1ReplyMessage message = V1ReplyMessageFactory.create();
+	private V1ReplyMessage message = V1ReplyMessageTestFactory.create();
 
 	@DisplayName("map V1ReplyMessage to PostfachNachricht")
 	@Nested
-- 
GitLab


From 6ad4b450683a4a582d42709a9ac00a56e6f127a3 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Tue, 28 Jan 2025 12:16:56 +0100
Subject: [PATCH 17/22] OZG-4095 wiremock: Remove mockserver dependency

---
 pom.xml | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/pom.xml b/pom.xml
index 1e8f3fd..0ad4730 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,6 @@
 	<properties>
 		<api-lib.version>0.16.0</api-lib.version>
 		<nachrichten-manager.version>2.17.0-SNAPSHOT</nachrichten-manager.version>
-		<mockserver-client.version>5.15.0</mockserver-client.version>
 		<openapi-generator.version>7.10.0</openapi-generator.version>
 		<swagger-parser.version>2.1.23</swagger-parser.version>
 		<wiremock-spring-boot.version>3.6.0</wiremock-spring-boot.version>
@@ -75,17 +74,6 @@
 			<version>${testcontainers.version}</version>
 			<scope>test</scope>
 		</dependency>
-		<dependency>
-			<groupId>org.mock-server</groupId>
-			<artifactId>mockserver-client-java</artifactId>
-			<version>${mockserver-client.version}</version>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.testcontainers</groupId>
-			<artifactId>mockserver</artifactId>
-			<scope>test</scope>
-		</dependency>
 
 		<dependency>
 			<groupId>org.wiremock.integrations</groupId>
-- 
GitLab


From 6f498a945feb0085f6f394d744edecc7965dfed8 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Tue, 28 Jan 2025 13:07:53 +0100
Subject: [PATCH 18/22] OZG-4095 base64: Use from testcontainer dependency

---
 .../de/ozgcloud/nachrichten/postfach/osiv2/extension/Jwt.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/Jwt.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/Jwt.java
index 327c91e..b8e053c 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/Jwt.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/extension/Jwt.java
@@ -5,7 +5,7 @@ import static de.ozgcloud.nachrichten.postfach.osiv2.factory.JsonUtil.*;
 import java.io.Serializable;
 import java.util.Map;
 
-import org.bouncycastle.util.encoders.Base64;
+import org.testcontainers.shaded.org.bouncycastle.util.encoders.Base64;
 
 import com.jayway.jsonpath.JsonPath;
 import com.jayway.jsonpath.ReadContext;
-- 
GitLab


From f6351d9bd1b50bf4e305188dd23189040ad0059b Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Tue, 28 Jan 2025 13:11:41 +0100
Subject: [PATCH 19/22] OZG-4095 stage-test: Use itcase profile

---
 .../postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
index 27c5c05..29f64ec 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
@@ -23,7 +23,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles({ "stage", "local" })
+@ActiveProfiles({ "stage", "itcase" })
 @EnabledIfEnvironmentVariable(named = "SH_STAGE_CLIENT_SECRET", matches = ".+")
 public class OsiPostfachRemoteServiceRemoteITCase {
 
-- 
GitLab


From ad21ba794148ba1e2aa537b5fb24965f89d47dd9 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Tue, 28 Jan 2025 15:34:11 +0100
Subject: [PATCH 20/22] OZG-4095 bean: Avoid name conflict of requestMapperImpl

---
 .../{RequestMapper.java => Osi2RequestMapper.java} |  2 +-
 ...ResponseMapper.java => Osi2ResponseMapper.java} |  3 +--
 .../osiv2/transfer/PostfachApiFacadeService.java   | 10 +++++-----
 ...tMapperTest.java => Osi2RequestMapperTest.java} |  4 ++--
 ...MapperTest.java => Osi2ResponseMapperTest.java} |  4 ++--
 .../transfer/PostfachApiFacadeServiceTest.java     | 14 +++++++-------
 6 files changed, 18 insertions(+), 19 deletions(-)
 rename src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/{RequestMapper.java => Osi2RequestMapper.java} (98%)
 rename src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/{ResponseMapper.java => Osi2ResponseMapper.java} (97%)
 rename src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/{RequestMapperTest.java => Osi2RequestMapperTest.java} (97%)
 rename src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/{ResponseMapperTest.java => Osi2ResponseMapperTest.java} (96%)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java
similarity index 98%
rename from src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java
rename to src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java
index c9a42ae..4b1482c 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java
@@ -17,7 +17,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1References;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
 
 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
-public interface RequestMapper {
+public interface Osi2RequestMapper {
 
 	@Mapping(target = "sequencenumber", source = "vorgangId")
 	@Mapping(target = "body", source = "mailBody")
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapper.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java
similarity index 97%
rename from src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapper.java
rename to src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java
index 84a1b80..f5acb80 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapper.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java
@@ -1,7 +1,6 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
 
 import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -17,7 +16,7 @@ import lombok.Builder;
 import lombok.Getter;
 
 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, imports = ZoneOffset.class)
-public interface ResponseMapper {
+public interface Osi2ResponseMapper {
 
 	String POSTFACH_ADDRESS_VERSION = "2.0";
 	int POSTFACH_ADDRESS_TYPE = 2;
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
index 7f62892..7d3651a 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
@@ -20,15 +20,15 @@ import lombok.extern.log4j.Log4j2;
 public class PostfachApiFacadeService {
 
 	private final MessageExchangeApi messageExchangeApi;
-	private final RequestMapper requestMapper;
-	private final  ResponseMapper responseMapper;
+	private final Osi2RequestMapper osi2RequestMapper;
+	private final Osi2ResponseMapper osi2ResponseMapper;
 
 	private static int MAX_NUMBER_RECEIVED_MESSAGES = 100;
 
 	public void sendMessage(PostfachNachricht nachricht) {
 		messageExchangeApi.sendMessage(
-				requestMapper.mapMailboxId(nachricht),
-				requestMapper.mapOutSendMessageRequestV2(nachricht)
+				osi2RequestMapper.mapMailboxId(nachricht),
+				osi2RequestMapper.mapOutSendMessageRequestV2(nachricht)
 		);
 	}
 
@@ -39,7 +39,7 @@ public class PostfachApiFacadeService {
 
 	PostfachNachricht fetchMessageByGuid(final MessageExchangeReceiveMessage message) {
 		var messageReply = messageExchangeApi.getMessage(message.getGuid());
-		return responseMapper.toPostfachNachricht(messageReply);
+		return osi2ResponseMapper.toPostfachNachricht(messageReply);
 	}
 
 	public void deleteMessage(final String messageId) {
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java
similarity index 97%
rename from src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java
rename to src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java
index 0e67c3c..3abec1a 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java
@@ -23,9 +23,9 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.OutSendMessageRequestV2;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1EidasLevel;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
 
-class RequestMapperTest {
+class Osi2RequestMapperTest {
 
-	private final RequestMapper mapper = Mappers.getMapper(RequestMapper.class);
+	private final Osi2RequestMapper mapper = Mappers.getMapper(Osi2RequestMapper.class);
 
 	@DisplayName("map mailbox id")
 	@Nested
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapperTest.java
similarity index 96%
rename from src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java
rename to src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapperTest.java
index d4c8706..3ec9b50 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/ResponseMapperTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapperTest.java
@@ -16,10 +16,10 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageFactory;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyMessage;
 
-class ResponseMapperTest {
+class Osi2ResponseMapperTest {
 
 	@InjectMocks
-	private ResponseMapper mapper = Mappers.getMapper(ResponseMapper.class);
+	private Osi2ResponseMapper mapper = Mappers.getMapper(Osi2ResponseMapper.class);
 	private V1ReplyMessage message = V1ReplyMessageFactory.create();
 
 	@DisplayName("map V1ReplyMessage to PostfachNachricht")
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java
index 139ba19..c1abebb 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java
@@ -32,10 +32,10 @@ class PostfachApiFacadeServiceTest {
 	MessageExchangeApi messageExchangeApi;
 
 	@Mock
-	RequestMapper requestMapper;
+	Osi2RequestMapper osi2RequestMapper;
 
 	@Mock
-	ResponseMapper responseMapper;
+	Osi2ResponseMapper osi2ResponseMapper;
 
 	@DisplayName("send message")
 	@Nested
@@ -51,8 +51,8 @@ class PostfachApiFacadeServiceTest {
 
 		@BeforeEach
 		void mock() {
-			when(requestMapper.mapMailboxId(nachricht)).thenReturn(MAILBOX_ID);
-			when(requestMapper.mapOutSendMessageRequestV2(nachricht)).thenReturn(outSendMessageRequestV2);
+			when(osi2RequestMapper.mapMailboxId(nachricht)).thenReturn(MAILBOX_ID);
+			when(osi2RequestMapper.mapOutSendMessageRequestV2(nachricht)).thenReturn(outSendMessageRequestV2);
 			when(messageExchangeApi.sendMessage(any(), any())).thenReturn(messageExchangeSendMessageResponse);
 		}
 
@@ -107,17 +107,17 @@ class PostfachApiFacadeServiceTest {
 		@Test
 		void shouldCallResponseMapper(){
 			when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage);
-			when(responseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
+			when(osi2ResponseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
 
 			postfachApiFacadeService.fetchMessageByGuid(receiveMessage);
 
-			verify(responseMapper).toPostfachNachricht(any());
+			verify(osi2ResponseMapper).toPostfachNachricht(any());
 		}
 
 		@Test
 		void shouldReturnPostfachNachricht(){
 			when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage);
-			when(responseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
+			when(osi2ResponseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
 
 			var postfachNachricht = postfachApiFacadeService.fetchMessageByGuid(receiveMessage);
 
-- 
GitLab


From 4316a99baabb7f49cc0a84ba07448dd98a046208 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Wed, 29 Jan 2025 16:51:56 +0100
Subject: [PATCH 21/22] OZG-4094 Fix NPE for empty messages

---
 .../postfach/osiv2/transfer/PostfachApiFacadeService.java  | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
index 7d3651a..b2b1499 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
@@ -1,5 +1,7 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
 
+import java.util.Collection;
+import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Stream;
 
@@ -34,7 +36,10 @@ public class PostfachApiFacadeService {
 
 	public Stream<PostfachNachricht> receiveMessages() {
 		var response = messageExchangeApi.receiveMessages(MAX_NUMBER_RECEIVED_MESSAGES, 0);
-		return response.getMessages().stream().map(this::fetchMessageByGuid);
+		return Optional.ofNullable(response.getMessages())
+				.stream()
+				.flatMap(Collection::stream)
+				.map(this::fetchMessageByGuid);
 	}
 
 	PostfachNachricht fetchMessageByGuid(final MessageExchangeReceiveMessage message) {
-- 
GitLab


From d8fbdaf38868d95719f869d474f343721c508211 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Thu, 30 Jan 2025 16:47:53 +0100
Subject: [PATCH 22/22] OZG-4094 merge: Adjust config values

---
 .../postfach/osiv2/config/Osi2PostfachProperties.java       | 6 +++---
 src/main/resources/application-stage.yml                    | 4 ++--
 .../postfach/osiv2/OsiPostfachRemoteServiceITCase.java      | 2 +-
 .../osiv2/OsiPostfachRemoteServiceRemoteITCase.java         | 1 -
 .../postfach/osiv2/OsiPostfachRemoteServiceTest.java        | 1 +
 src/test/resources/application-itcase.yml                   | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
index 6d4bb53..81ef462 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/Osi2PostfachProperties.java
@@ -17,7 +17,7 @@ import lombok.Setter;
 @RequiredArgsConstructor
 public class Osi2PostfachProperties {
 
-	static final String PREFIX = "ozgcloud.osiv2";
+	public static final String PREFIX = "ozgcloud.osiv2";
 
 	private boolean enabled;
 
@@ -30,7 +30,7 @@ public class Osi2PostfachProperties {
 	@Configuration
 	@ConfigurationProperties(prefix = ApiConfiguration.PREFIX)
 	public static class ApiConfiguration {
-		static final String PREFIX = Osi2PostfachProperties.PREFIX + ".api";
+		public static final String PREFIX = Osi2PostfachProperties.PREFIX + ".api";
 
 		private String resource;
 		private String url;
@@ -47,7 +47,7 @@ public class Osi2PostfachProperties {
 	@Configuration
 	@ConfigurationProperties(prefix = ProxyConfiguration.PREFIX)
 	public static class ProxyConfiguration {
-		static final String PREFIX = Osi2PostfachProperties.PREFIX + ".proxy";
+		public static final String PREFIX = Osi2PostfachProperties.PREFIX + ".proxy";
 
 		private boolean enabled;
 
diff --git a/src/main/resources/application-stage.yml b/src/main/resources/application-stage.yml
index 6892480..c2804ac 100644
--- a/src/main/resources/application-stage.yml
+++ b/src/main/resources/application-stage.yml
@@ -13,14 +13,14 @@ spring:
           osi2:
             token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token'
 ozgcloud:
-  osiv2-postfach:
+  osiv2:
     enabled: false
     api:
       resource: 'urn:dataport:osi:postfach:rz2:stage:sh'
       url: 'https://api-gateway-stage.dataport.de:443/api/osi_postfach/1.0.0'
       tenant: 'SH'
       name-identifier: 'ozgkopfstelle'
-    http-proxy:
+    proxy:
       enabled: true
       host: 127.0.0.1
       port: 3128
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
index d521985..53c668b 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -38,7 +38,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMe
 import lombok.SneakyThrows;
 
 @SpringBootTest(classes = TestApplication.class)
-@ActiveProfiles({"stage", "itcase"})
+@ActiveProfiles({ "stage", "itcase" })
 @TestPropertySource(properties = {
 		"ozgcloud.osiv2.proxy.enabled=false",
 })
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
index 482ed08..bfe893d 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java
@@ -6,7 +6,6 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java
index a00ab88..685c36f 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java
@@ -81,6 +81,7 @@ class OsiPostfachRemoteServiceTest {
 
 			verify(postfachApiFacadeService).deleteMessage(any());
 		}
+
 		@DisplayName("should throw osi postfach exception on runtime exception")
 		@Test
 		void shouldThrowOsiPostfachExceptionOnRuntimeException() {
diff --git a/src/test/resources/application-itcase.yml b/src/test/resources/application-itcase.yml
index d8cacf7..41e8478 100644
--- a/src/test/resources/application-itcase.yml
+++ b/src/test/resources/application-itcase.yml
@@ -1,5 +1,5 @@
 ozgcloud:
-  osiv2-postfach:
+  osiv2:
     enabled: true
 logging:
   level:
-- 
GitLab