From 70cc3ee518b55490ad1a08836d44104b5d995926 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Wed, 6 Nov 2024 09:12:02 +0100
Subject: [PATCH] #2 itcase-setup: Try out sending dummy message

---
 pom.xml                                       | 17 ++++-
 .../osiv2/OsiPostfachRemoteService.java       | 11 ++-
 .../osiv2/config/WebClientConfiguration.java  | 44 +++++++++++
 src/main/resources/application.yml            | 16 +++-
 .../osiv2/OsiPostfachRemoteServiceITCase.java | 74 +++++++++++++++++--
 .../postfach/osiv2/TestApplication.java       |  9 +++
 6 files changed, 158 insertions(+), 13 deletions(-)
 create mode 100644 src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/WebClientConfiguration.java
 create mode 100644 src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/TestApplication.java

diff --git a/pom.xml b/pom.xml
index 28be7a0..a0bba2b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,7 @@
 		<api-lib.version>0.13.0</api-lib.version>
 		<nachrichten-manager.version>2.14.0</nachrichten-manager.version>
 		<testcontainers-keycloak.version>3.2.0</testcontainers-keycloak.version>
+		<mockserver-client.version>5.15.0</mockserver-client.version>
 	</properties>
 	<dependencies>
 		<!-- OZG-Cloud -->
@@ -36,15 +37,15 @@
 
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-web</artifactId>
+			<artifactId>spring-boot-starter-validation</artifactId>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-validation</artifactId>
+			<artifactId>spring-boot-starter-oauth2-client</artifactId>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-oauth2-client</artifactId>
+			<artifactId>spring-boot-starter-webflux</artifactId>
 		</dependency>
 
 		<dependency>
@@ -76,6 +77,16 @@
 			<artifactId>junit-jupiter-engine</artifactId>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+			<groupId>org.mock-server</groupId>
+			<artifactId>mockserver-client-java</artifactId>
+			<version>${mockserver-client.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mock-server</groupId>
+			<artifactId>mockserver-netty</artifactId>
+			<version>${mockserver-client.version}</version>
+		</dependency>
 
 		<dependency>
 			<groupId>org.springframework.cloud</groupId>
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 f3c3195..3e7704c 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
@@ -2,17 +2,26 @@ package de.ozgcloud.nachrichten.postfach.osiv2;
 
 import java.util.stream.Stream;
 
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
+import org.springframework.web.reactive.function.client.WebClient;
 
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
 
 @Service
-public class OsiPostfachRemoteService implements PostfachRemoteService {
+public record OsiPostfachRemoteService(
+		@Qualifier("osi2PostfachWebClient") WebClient webClient
+) implements PostfachRemoteService {
 	public static final String POSTFACH_TYPE_OSIV2 = "OSIV2";
 
 	@Override
 	public void sendMessage(PostfachNachricht nachricht) {
+		webClient.get()
+				.uri("/dummy")
+				.retrieve()
+				.bodyToMono(String.class)
+				.block();
 		// TODO
 	}
 
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/WebClientConfiguration.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/WebClientConfiguration.java
new file mode 100644
index 0000000..df081b1
--- /dev/null
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/WebClientConfiguration.java
@@ -0,0 +1,44 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@Configuration
+public class WebClientConfiguration {
+
+	@Bean("osi2PostfachWebClient")
+	public WebClient osi2PostfachWebClient(
+			ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction) {
+		return WebClient.builder()
+				.filter(serverOAuth2AuthorizedClientExchangeFilterFunction)
+				.build();
+	}
+
+	@Bean
+	@Primary
+	ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction(
+			ReactiveClientRegistrationRepository clientRegistrations) {
+		var clientService = new InMemoryReactiveOAuth2AuthorizedClientService(
+				clientRegistrations);
+		var authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
+				clientRegistrations, clientService);
+
+		authorizedClientManager.setAuthorizedClientProvider(
+				ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
+						.clientCredentials()
+						.build());
+
+		var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
+				authorizedClientManager);
+		oauth.setDefaultClientRegistrationId("osi2");
+		return oauth;
+	}
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 065fffe..d4cb32c 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,3 +1,17 @@
 spring:
+  main:
+    web-application-type: reactive
   jackson:
-    default-property-inclusion: NON_NULL
\ No newline at end of file
+    default-property-inclusion: NON_NULL
+  security:
+    oauth2:
+      client:
+        registration:
+          osi2:
+            client-id: 'OZG-Kopfstelle'
+            client-secret: 'changeme'
+            scope: default, access_urn:some:scope:for:ozgkopfstelle
+            authorization-grant-type: 'client_credentials'
+        provider:
+          osi2:
+            token-uri: 'replaceme'
\ 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 a9892fd..ea14676 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java
@@ -1,15 +1,27 @@
 package de.ozgcloud.nachrichten.postfach.osiv2;
 
+import static org.assertj.core.api.Assertions.*;
+import static org.mockserver.model.HttpRequest.*;
+import static org.mockserver.model.HttpResponse.*;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.mockserver.client.MockServerClient;
+import org.mockserver.matchers.Times;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
 
 import dasniko.testcontainers.keycloak.KeycloakContainer;
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 
-@SpringBootTest(classes = OsiPostfachRemoteService.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
 public class OsiPostfachRemoteServiceITCase {
 	private static final String MESSAGE_ID = "message-id";
 
@@ -20,17 +32,63 @@ public class OsiPostfachRemoteServiceITCase {
 	@Autowired
 	private OsiPostfachRemoteService osiPostfachRemoteService;
 
+	private static MockServerClient mockServerClient;
+	private static KeycloakContainer keycloakContainer;
+
+	@BeforeAll
+	public static void setupAll() {
+		mockServerClient = new MockServerClient("127.0.0.1", 1080);
+		keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:24.0.5")
+				.withRealmImportFile("keycloak-realm.json");
+		keycloakContainer.start();
+	}
+
+	@DynamicPropertySource
+	static void dynamicProperties(DynamicPropertyRegistry registry) {
+		registry.add("spring.security.oauth2.client.provider.osi2.token-uri", () ->
+				keycloakContainer.getAuthServerUrl() + "/webidp2/connect/token");
+	}
+
+	@AfterAll
+	public static void tearDownAll() {
+		mockServerClient.stop();
+		keycloakContainer.stop();
+	}
+
+	@BeforeEach
+	public void setup() {
+		mockServerClient
+				.when(
+						request()
+								.withMethod("GET")
+								.withPath("/dummy"),
+						Times.exactly(1)
+				)
+				.respond(
+						response()
+								.withStatusCode(200)
+				);
+	}
+
+	@AfterEach
+	public void tearDown() {
+		mockServerClient.reset();
+	}
+
 	@DisplayName("send message")
 	@Nested
 	class TestSendMessage {
-		@DisplayName("should not fail")
+		@DisplayName("should send dummy request")
 		@Test
-		void shouldNotFail() {
-			try (var keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:24.0.5")
-					.withRealmImportFile("keycloak-realm.json")) {
-				keycloakContainer.start();
-				osiPostfachRemoteService.sendMessage(postfachNachricht);
-			}
+		void shouldSendDummyRequest() {
+			osiPostfachRemoteService.sendMessage(postfachNachricht);
+
+			var requests = mockServerClient.retrieveRecordedRequests(
+					request()
+							.withMethod("GET")
+							.withPath("/dummy")
+			);
+			assertThat(requests).hasSize(1);
 		}
 	}
 }
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/TestApplication.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/TestApplication.java
new file mode 100644
index 0000000..afa904e
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/TestApplication.java
@@ -0,0 +1,9 @@
+package de.ozgcloud.nachrichten.postfach.osiv2;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@AutoConfiguration
+public class TestApplication {
+}
-- 
GitLab