diff --git a/pom.xml b/pom.xml index e373fe58bc4e49a221adf1f87747306731589e8c..12802c88bda7ee8a0ad01701ce78443c3707c2a0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-parent</artifactId> - <version>4.6.0</version> + <version>4.9.0</version> </parent> <groupId>de.ozgcloud.osiv2</groupId> @@ -42,13 +42,14 @@ </dependency> <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-oauth2-client</artifactId> + <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-webflux</artifactId> + <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> + <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> @@ -91,7 +92,10 @@ <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> - + <dependency> + <groupId>org.apache.httpcomponents.client5</groupId> + <artifactId>httpclient5</artifactId> + </dependency> <!-- used by generated code --> <!-- @Nullable annotation --> <dependency> @@ -148,7 +152,7 @@ <configOptions> <sourceFolder>src/gen/java/main</sourceFolder> <serializationLibrary>jackson</serializationLibrary> - <library>webclient</library> + <library>restclient</library> <annotationLibrary>swagger2</annotationLibrary> <apiPackage>de.ozgcloud.nachrichten.postfach.osiv2.gen.api</apiPackage> <modelPackage>de.ozgcloud.nachrichten.postfach.osiv2.gen.model</modelPackage> 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 6559227d384fd2af43f561149553e38c91029b82..89761838c98336a31ca91d874373d5efa68792d1 100644 --- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java +++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java @@ -11,7 +11,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.transfer.PostfachApiFacadeService; import lombok.extern.log4j.Log4j2; @Service -@ConditionalOnProperty("ozgcloud.osiv2-postfach.enabled") +@ConditionalOnProperty("ozgcloud.osiv2.enabled") @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 16d7d79b1155b63b0dffbbc6a87351ecf1aecbc0..9461adf1ce8b2cd24e67761d643680130f2a5f53 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,29 +1,37 @@ package de.ozgcloud.nachrichten.postfach.osiv2.config; +import de.ozgcloud.nachrichten.postfach.osiv2.gen.ApiClient; +import de.ozgcloud.nachrichten.postfach.osiv2.gen.api.MessageExchangeApi; +import lombok.RequiredArgsConstructor; +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; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.core5.http.HttpHost; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; -import org.springframework.security.oauth2.client.endpoint.WebClientReactiveClientCredentialsTokenResponseClient; -import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; +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.reactive.function.client.WebClient; - -import de.ozgcloud.nachrichten.postfach.osiv2.gen.ApiClient; -import de.ozgcloud.nachrichten.postfach.osiv2.gen.api.MessageExchangeApi; -import lombok.RequiredArgsConstructor; -import reactor.netty.http.client.HttpClient; -import reactor.netty.transport.ProxyProvider; +import org.springframework.web.client.RestClient; @Configuration +@EnableWebSecurity @RequiredArgsConstructor -@ConditionalOnProperty("ozgcloud.osiv2-postfach.enabled") +@ConditionalOnProperty("ozgcloud.osiv2.enabled") public class ApiClientConfiguration { private final OsiPostfachProperties.ApiConfiguration apiConfiguration; @@ -35,45 +43,57 @@ public class ApiClientConfiguration { } @Bean - ApiClient apiClient(ReactiveClientRegistrationRepository clientRegistrations) { - return new ApiClient(osi2PostfachWebClient(clientRegistrations)) - .setBasePath(apiConfiguration.getUrl()); + ApiClient apiClient(RestClient restClient) { + var apiClient = new ApiClient(restClient); + apiClient.setBasePath(apiConfiguration.getUrl()); + return apiClient; } - private WebClient osi2PostfachWebClient( - ReactiveClientRegistrationRepository clientRegistrations) { - return WebClient.builder() - .clientConnector(new ReactorClientHttpConnector(httpClient())) - .filter(serverOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations)) + @Bean + public RestClient restClient(ClientRegistrationRepository clientRegistrations) { + OAuth2ClientHttpRequestInterceptor requestInterceptor = + new OAuth2ClientHttpRequestInterceptor(authorizedClientManager(clientRegistrations)); + requestInterceptor.setClientRegistrationIdResolver(request -> "osi2"); + + return defaultRestClientBuilder() + .requestInterceptor(requestInterceptor) .build(); } - @SuppressWarnings("ConstantConditions") - private HttpClient httpClient() { - var webClient = HttpClient.create(); - return proxyConfiguration.isEnabled() ? webClient - .proxy(proxy -> proxy - .type(ProxyProvider.Proxy.HTTP) - .host(proxyConfiguration.getHost()) - .port(proxyConfiguration.getPort()) - .username(proxyConfiguration.getUsername()) - .password(username -> proxyConfiguration.getPassword()) - ) : webClient; + private RestClient.Builder defaultRestClientBuilder() { + return RestClient.builder() + .requestFactory(createProxyRequestFactory()); } - private ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction( - ReactiveClientRegistrationRepository clientRegistrations) { + private ClientHttpRequestFactory createProxyRequestFactory() { + var requestFactory = new HttpComponentsClientHttpRequestFactory(); + if (proxyConfiguration.isEnabled()) { + requestFactory.setHttpClient( + HttpClientBuilder.create() + .setProxy(new HttpHost(proxyConfiguration.getHost(), proxyConfiguration.getPort())) + .setDefaultCredentialsProvider(basicCredentialsProviderForProxy()) + .build() + ); + } + return requestFactory; + } - var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager(clientRegistrations)); - oauth.setDefaultClientRegistrationId("osi2"); - return oauth; + 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 AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager( - ReactiveClientRegistrationRepository clientRegistrations) { - var clientService = new InMemoryReactiveOAuth2AuthorizedClientService( + private AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager( + ClientRegistrationRepository clientRegistrations) { + var clientService = new InMemoryOAuth2AuthorizedClientService( clientRegistrations); - var authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager( + var authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrations, clientService); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider()); @@ -81,28 +101,33 @@ public class ApiClientConfiguration { return authorizedClientManager; } - private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider() { - return ReactiveOAuth2AuthorizedClientProviderBuilder.builder() + private OAuth2AuthorizedClientProvider authorizedClientProvider() { + return OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials(builder -> builder.accessTokenResponseClient(clientCredentialsTokenResponseClient()) ) .build(); } - private WebClientReactiveClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient() { - var client = new WebClientReactiveClientCredentialsTokenResponseClient(); - configureHttpClientForTokenRequests(client); + private RestClientClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient() { + var client = new RestClientClientCredentialsTokenResponseClient(); + configureClientCredentialsRestClient(client); configureParametersForTokenRequests(client); return client; } - private void configureHttpClientForTokenRequests(WebClientReactiveClientCredentialsTokenResponseClient client) { - client.setWebClient(WebClient.builder() - .clientConnector(new ReactorClientHttpConnector(httpClient())) + 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(WebClientReactiveClientCredentialsTokenResponseClient 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 diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java index 44fd8ef163bbfae627be0353f5346af4a4944dbc..5d1df86ea4cefa8fc177ffe8545273de464fd4c8 100644 --- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java +++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/config/OsiPostfachProperties.java @@ -14,7 +14,7 @@ import lombok.Setter; @ConfigurationProperties(prefix = OsiPostfachProperties.PREFIX) public class OsiPostfachProperties { - static final String PREFIX = "ozgcloud.osiv2-postfach"; + static final String PREFIX = "ozgcloud.osiv2"; private boolean enabled; @@ -40,7 +40,7 @@ public class OsiPostfachProperties { @Configuration @ConfigurationProperties(prefix = ProxyConfiguration.PREFIX) static class ProxyConfiguration { - static final String PREFIX = OsiPostfachProperties.PREFIX + ".http-proxy"; + static final String PREFIX = OsiPostfachProperties.PREFIX + ".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 246a12108b9fdc919df2bd87b11aa93219f71d8a..c815b32ed002daf1ddb9d0da2bb35a02300a5df7 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 @@ -13,7 +13,7 @@ import lombok.extern.log4j.Log4j2; @Log4j2 @Service -@ConditionalOnProperty("ozgcloud.osiv2-postfach.enabled") +@ConditionalOnProperty("ozgcloud.osiv2.enabled") public record PostfachApiFacadeService(MessageExchangeApi messageExchangeApi, RequestMapper requestMapper, ResponseMapper responseMapper) { private static int MAX_NUMBER_RECEIVED_MESSAGES = 100; @@ -21,21 +21,21 @@ public record PostfachApiFacadeService(MessageExchangeApi messageExchangeApi, Re messageExchangeApi.sendMessage( requestMapper.mapMailboxId(nachricht), requestMapper.mapOutSendMessageRequestV2(nachricht) - ).block(); + ); } public Stream<PostfachNachricht> receiveMessages() { - var response = messageExchangeApi.receiveMessages(MAX_NUMBER_RECEIVED_MESSAGES, 0).block(); + var response = messageExchangeApi.receiveMessages(MAX_NUMBER_RECEIVED_MESSAGES, 0); return response.getMessages().stream().map(this::fetchMessageByGuid); } PostfachNachricht fetchMessageByGuid(final MessageExchangeReceiveMessage message) { - var messageReply = messageExchangeApi.getMessage(message.getGuid()).block(); + var messageReply = messageExchangeApi.getMessage(message.getGuid()); return responseMapper.toPostfachNachricht(messageReply); } public void deleteMessage(final String messageId) { - messageExchangeApi.deleteMessage(UUID.fromString(messageId)).block(); + messageExchangeApi.deleteMessage(UUID.fromString(messageId)); } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 172d0ad8a7a1e127b094913f30707cc9e805b69e..e9a716309c13d9d5b2f5c35401dfaead0e6f5b2c 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: @@ -17,14 +15,14 @@ spring: osi2: token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token' ozgcloud: - osiv2-postfach: + osiv2: 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: + 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 2c07c7829eecea5369ae091c96b892161fe2095d..a99d657d13afe1860ddd9532548ca37dc0c3fa58 100644 --- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java +++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceITCase.java @@ -7,15 +7,15 @@ 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 de.ozgcloud.nachrichten.postfach.osiv2.factory.JsonUtil; +import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -29,24 +29,18 @@ 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.PostfachNachrichtTestFactory; 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, webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = TestApplication.class) @ActiveProfiles("itcase") @TestPropertySource(properties = { - "ozgcloud.osiv2-postfach.http-proxy.enabled=false", + "ozgcloud.osiv2.proxy.enabled=false", }) public class OsiPostfachRemoteServiceITCase { @@ -63,29 +57,74 @@ public class OsiPostfachRemoteServiceITCase { registry.add("spring.security.oauth2.client.provider.osi2.token-uri", OSI_MOCK_SERVER_EXTENSION::getAccessTokenUrl); registry.add("spring.security.oauth2.client.registration.osi2.scope", () -> CLIENT_SCOPES); registry.add("spring.security.oauth2.client.registration.osi2.client-id", () -> CLIENT_ID); - registry.add("ozgcloud.osiv2-postfach.api.url", OSI_MOCK_SERVER_EXTENSION::getPostfachFacadeUrl); - registry.add("ozgcloud.osiv2-postfach.api.resource", () -> RESOURCE_URN); + registry.add("ozgcloud.osiv2.api.url", OSI_MOCK_SERVER_EXTENSION::getPostfachFacadeUrl); + registry.add("ozgcloud.osiv2.api.resource", () -> RESOURCE_URN); } private MockServerClient postfachFacadeMockClient; - @BeforeEach + @SneakyThrows + 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) + ); + } + + @SneakyThrows + private static String getPostfachApiSpec() { + return Files.readString(Path.of("spec", "postfach-api-facade.yaml")); + } + + 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 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)) + ); + } + + + @BeforeEach @SneakyThrows public void setup() { postfachFacadeMockClient = OSI_MOCK_SERVER_EXTENSION.getPostfachFacadeMockClient(); } + @DisplayName("should send dummy 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); @@ -98,17 +137,12 @@ public class OsiPostfachRemoteServiceITCase { assertThat(jwt.body().read("$.aud", String.class)).isEqualTo(RESOURCE_URN); } - ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()); @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(); @@ -116,68 +150,36 @@ public class OsiPostfachRemoteServiceITCase { assertThat(messageList).size().isEqualTo(1); } + @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"); - - createMessagesJson(uuid1, uuid2); - - createOneReplyMessageJson(uuid1); - createOneReplyMessageJson(uuid2); - - var messageStream = osiPostfachRemoteService.getAllMessages(); - - var messageList = messageStream.toList(); - assertThat(messageList).size().isEqualTo(2); - } + mockPostfachMessageAndResponse("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000001"); - private void createMessagesJson(final UUID... uuids) throws IOException { - var messagesList = Arrays.stream(uuids).filter(Objects::nonNull).map(uuid -> new MessageExchangeReceiveMessage().guid(uuid)).toList(); + var messageList = osiPostfachRemoteService.getAllMessages().toList(); - var messages = new MessageExchangeReceiveMessagesResponse().messages(messagesList); - - ObjectWriter ow = objectMapper.writer().withDefaultPrettyPrinter(); - String messagesJson = ow.writeValueAsString(messages); - - createMessagesCall("receiveMessages", messagesJson); - } - - private void createMessagesCall(final String receiveMessages, final String messagesJson) throws IOException { - postfachFacadeMockClient - .when( - new OpenAPIDefinition() - .withSpecUrlOrPayload(Files.readString(Path.of("spec", "postfach-api-facade.yaml"))) - .withOperationId(receiveMessages) - ) - .respond(response().withHeader("Content-type", "application/json").withBody(messagesJson)); + assertThat(messageList).hasSize(2); } - 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); - } @DisplayName("should delete message") @Test @SneakyThrows void shouldDeleteMessage() { - postfachFacadeMockClient.upsert( - openAPIExpectation() - .withSpecUrlOrPayload(Files.readString(Path.of("spec", "postfach-api-facade.yaml"))) - .withOperationsAndResponses(Map.of( - "deleteMessage", "200" - )) - ); + mockOperationsAndResponses(Map.of( + "deleteMessage", "200" + )); assertDoesNotThrow(() -> osiPostfachRemoteService.deleteMessage("00000000-0000-0000-0000-000000000000")); + + var requests = postfachFacadeMockClient.retrieveRecordedRequests(request()); + + assertThat(requests[0].getMethod()).isEqualTo("DELETE"); + assertThat(requests[0].getPath()).isEqualTo("/MessageExchange/v1/Delete/00000000-0000-0000-0000-000000000000"); + } + + } 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 344c3de7e35a2f68761a726cf963248aae4dbcf8..778e843e5754290f41e1c8f66e299440a99b44a0 100644 --- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java +++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java @@ -22,8 +22,8 @@ import de.ozgcloud.nachrichten.postfach.osiv2.factory.DummyStringBasedIdentifier import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory; import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory; -@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) -@ActiveProfiles("itcase") +@SpringBootTest(classes = TestApplication.class) +@ActiveProfiles("local") @EnabledIfEnvironmentVariable(named = "SH_STAGE_CLIENT_SECRET", matches = ".+") public class OsiPostfachRemoteServiceRemoteITCase { @@ -46,11 +46,11 @@ public class OsiPostfachRemoteServiceRemoteITCase { () -> System.getenv("SH_STAGE_CLIENT_SECRET") ); registry.add( - "ozgcloud.osiv2-postfach.http-proxy.host", + "ozgcloud.osiv2.proxy.host", () -> matchProxyRegex(System.getenv("HTTP_PROXY")).group(1) ); registry.add( - "ozgcloud.osiv2-postfach.http-proxy.port", + "ozgcloud.osiv2.proxy.port", () -> matchProxyRegex(System.getenv("HTTP_PROXY")).group(2) ); } @@ -63,7 +63,6 @@ public class OsiPostfachRemoteServiceRemoteITCase { throw new IllegalArgumentException("Proxy host and port not found in '%s'".formatted(text)); } - @Disabled @DisplayName("send message") @Nested class TestSendMessage { @@ -88,7 +87,6 @@ public class OsiPostfachRemoteServiceRemoteITCase { } } - @Disabled @DisplayName("delete message") @Nested class TestDeleteMessageById{ 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 5ce2169b26b87ac81589556b0a6f5469d89f68fb..9d59d950c805922702d0a18bf38cbdb30e6c3a5c 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( 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 5353606ac693ef6d98d03dc58d77d900c4943279..fb9565d6714674ce91bdd0d275c67e46b91a0c76 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 @@ -2,10 +2,11 @@ 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) { 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 f8a3c19c34125ece0bf242dea493888a2fd2050c..139ba192c9394ddb55d2657e094a2d9d15765866 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 @@ -22,7 +22,6 @@ import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMe import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeSendMessageResponse; import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.OutSendMessageRequestV2; import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyMessage; -import reactor.core.publisher.Mono; class PostfachApiFacadeServiceTest { @@ -52,10 +51,9 @@ class PostfachApiFacadeServiceTest { @BeforeEach void mock() { - var responseMono = Mono.just(messageExchangeSendMessageResponse); when(requestMapper.mapMailboxId(nachricht)).thenReturn(MAILBOX_ID); when(requestMapper.mapOutSendMessageRequestV2(nachricht)).thenReturn(outSendMessageRequestV2); - when(messageExchangeApi.sendMessage(any(), any())).thenReturn(responseMono); + when(messageExchangeApi.sendMessage(any(), any())).thenReturn(messageExchangeSendMessageResponse); } @DisplayName("should call sendMessage") @@ -77,8 +75,7 @@ class PostfachApiFacadeServiceTest { @BeforeEach void mock(){ - var responseMono = Mono.just(messageExchangeReceiveMessagesResponse); - when(messageExchangeApi.receiveMessages(anyInt(),anyInt())).thenReturn(responseMono); + when(messageExchangeApi.receiveMessages(anyInt(),anyInt())).thenReturn(messageExchangeReceiveMessagesResponse); } @Test @@ -100,8 +97,7 @@ class PostfachApiFacadeServiceTest { @Test void shouldCallGetMessage(){ - var replyMono = Mono.just(replyMessage); - when(messageExchangeApi.getMessage(any())).thenReturn(replyMono); + when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage); postfachApiFacadeService.fetchMessageByGuid(receiveMessage); @@ -110,8 +106,7 @@ class PostfachApiFacadeServiceTest { @Test void shouldCallResponseMapper(){ - var replyMono = Mono.just(replyMessage); - when(messageExchangeApi.getMessage(any())).thenReturn(replyMono); + when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage); when(responseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create()); postfachApiFacadeService.fetchMessageByGuid(receiveMessage); @@ -121,8 +116,7 @@ class PostfachApiFacadeServiceTest { @Test void shouldReturnPostfachNachricht(){ - var replyMono = Mono.just(replyMessage); - when(messageExchangeApi.getMessage(any())).thenReturn(replyMono); + when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage); when(responseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create()); var postfachNachricht = postfachApiFacadeService.fetchMessageByGuid(receiveMessage); @@ -139,8 +133,7 @@ class PostfachApiFacadeServiceTest { @Test void shouldCallDeleteMessage(){ - var replyMono = Mono.just(replyMessage); - when(messageExchangeApi.deleteMessage(any())).thenReturn(replyMono); + when(messageExchangeApi.deleteMessage(any())).thenReturn(replyMessage); postfachApiFacadeService.deleteMessage(UUID.randomUUID().toString());