From 72f4cf3783e137e165db4f83ea0124f1c6ace372 Mon Sep 17 00:00:00 2001
From: Pavel Vetokhin
Date: Mon, 4 Mar 2024 21:11:27 +0300
Subject: [PATCH] Add view endpoint and test
---
.../bezmen/messaging/SepulkaClientIT.java | 21 +++++++++
.../bezmen/core/SepulkaServiceImpl.java | 10 ++--
.../bezmen/messaging/SepulkaClientImpl.java | 10 ++++
.../springmvc/SepulkaController.java | 18 ++++++--
.../bezmen/messaging/SepulkaClientIT.kt | 21 +++++++++
.../bezmen/core/SepulkaServiceImpl.kt | 8 ++--
.../bezmen/messaging/SepulkaClientImpl.kt | 9 ++++
.../messaging/springmvc/SepulkaController.kt | 20 ++++++--
.../bezmen/messaging/SepulkaClient.java | 4 ++
.../bezmen/messaging/SepulkaMessageEm.java | 15 ++++++
.../bezmen/messaging/SepulkaMessageEmEg.java | 26 +++++++++++
.../bezmen/core/SepulkaMessageDm.java | 4 +-
.../bezmen/core/SepulkaMessageDmEg.java | 9 ++++
.../bezmen/core/SepulkaService.java | 7 ++-
lib/essentials/pom.xml | 7 ++-
lib/messaging-client/pom.xml | 8 ++--
.../messaging/BezmenClientJavaHttp.java | 27 +++++++++--
.../messaging/SepulkaMessageMapper.java | 4 ++
.../bezmen/construction/StandBeans.java | 23 ++++++++++
.../{ToySuite.java => ResilienceSuite.java} | 4 +-
.../bezmen/registration/SepulkaTest.java | 13 ------
.../resilience/AbstractResilienceTest.java | 37 +++++++++++++++
.../bezmen/resilience/SepulkaTest.java | 43 +++++++++++++++++
.../src/test/resources/docker-java.properties | 0
tool/pom.xml | 17 +++++++
tool/testing/pom.xml | 13 +++++-
.../messaging/SepulkaClientSpringWebTest.java | 13 ++++++
.../smecalculus/bezmen/testing/Demiurge.java | 46 +++++++++++++++++++
28 files changed, 392 insertions(+), 45 deletions(-)
rename test/e2e/src/test/java/smecalculus/bezmen/{ToySuite.java => ResilienceSuite.java} (61%)
create mode 100644 test/e2e/src/test/java/smecalculus/bezmen/resilience/AbstractResilienceTest.java
create mode 100644 test/e2e/src/test/java/smecalculus/bezmen/resilience/SepulkaTest.java
create mode 100644 test/e2e/src/test/resources/docker-java.properties
create mode 100644 tool/testing/src/main/java/smecalculus/bezmen/testing/Demiurge.java
diff --git a/app/sepuling-java/src/it/java/smecalculus/bezmen/messaging/SepulkaClientIT.java b/app/sepuling-java/src/it/java/smecalculus/bezmen/messaging/SepulkaClientIT.java
index 246f2658..287c47ff 100644
--- a/app/sepuling-java/src/it/java/smecalculus/bezmen/messaging/SepulkaClientIT.java
+++ b/app/sepuling-java/src/it/java/smecalculus/bezmen/messaging/SepulkaClientIT.java
@@ -11,6 +11,7 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import smecalculus.bezmen.construction.SepulkaClientBeans;
+import smecalculus.bezmen.core.SepulkaMessageDm;
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationRequest;
import smecalculus.bezmen.core.SepulkaMessageDmEg;
import smecalculus.bezmen.core.SepulkaService;
@@ -44,4 +45,24 @@ void shouldRegisterSepulka() {
.ignoringExpectedNullFields()
.isEqualTo(expectedResponse);
}
+
+ @Test
+ void shouldViewSepulka() {
+ // given
+ var externalId = UUID.randomUUID().toString();
+ // and
+ var request = SepulkaMessageEmEg.viewRequest(externalId);
+ // and
+ when(serviceMock.view(any(SepulkaMessageDm.ViewRequest.class)))
+ .thenReturn(SepulkaMessageDmEg.viewResponse(externalId).build());
+ // and
+ var expectedResponse = SepulkaMessageEmEg.viewResponse(externalId);
+ // when
+ var actualResponse = externalClient.view(request);
+ // then
+ assertThat(actualResponse)
+ .usingRecursiveComparison()
+ .ignoringExpectedNullFields()
+ .isEqualTo(expectedResponse);
+ }
}
diff --git a/app/sepuling-java/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java b/app/sepuling-java/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java
index e1a8a837..1e931d6a 100644
--- a/app/sepuling-java/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java
+++ b/app/sepuling-java/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java
@@ -3,14 +3,12 @@
import static java.util.UUID.randomUUID;
import java.time.LocalDateTime;
-import java.util.Collections;
-import java.util.List;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
-import smecalculus.bezmen.core.SepulkaMessageDm.PreviewRequest;
-import smecalculus.bezmen.core.SepulkaMessageDm.PreviewResponse;
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationRequest;
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationResponse;
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewRequest;
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewResponse;
import smecalculus.bezmen.storage.SepulkaDao;
@RequiredArgsConstructor
@@ -37,7 +35,7 @@ public RegistrationResponse register(RegistrationRequest request) {
}
@Override
- public List view(PreviewRequest request) {
- return Collections.emptyList();
+ public ViewResponse view(ViewRequest request) {
+ return new ViewResponse(request.externalId());
}
}
diff --git a/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java b/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java
index be2502c7..2e2cef20 100644
--- a/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java
+++ b/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java
@@ -5,6 +5,8 @@
import smecalculus.bezmen.core.SepulkaService;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse;
import smecalculus.bezmen.validation.EdgeValidator;
@RequiredArgsConstructor
@@ -26,4 +28,12 @@ public RegistrationResponse register(RegistrationRequest requestEdge) {
var response = service.register(request);
return mapper.toEdge(response);
}
+
+ @Override
+ public ViewResponse view(ViewRequest requestEdge) {
+ validator.validate(requestEdge);
+ var request = mapper.toDomain(requestEdge);
+ var response = service.view(request);
+ return mapper.toEdge(response);
+ }
}
diff --git a/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java b/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java
index d206cbdf..3c71e81c 100644
--- a/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java
+++ b/app/sepuling-java/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java
@@ -4,13 +4,17 @@
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import smecalculus.bezmen.messaging.SepulkaClient;
+import smecalculus.bezmen.messaging.SepulkaMessageEm;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse;
@RestController
@RequestMapping("sepulkas")
@@ -21,8 +25,16 @@ public class SepulkaController {
private SepulkaClient client;
@PostMapping
- ResponseEntity register(@RequestBody RegistrationRequest requestEdge) {
- var responseEdge = client.register(requestEdge);
- return ResponseEntity.status(HttpStatus.CREATED).body(responseEdge);
+ ResponseEntity register(@RequestBody RegistrationRequest request) {
+ var response = client.register(request);
+ return ResponseEntity.status(HttpStatus.CREATED).body(response);
+ }
+
+ @GetMapping("/{externalId}")
+ ResponseEntity view(@PathVariable("externalId") String externalId) {
+ var request = new SepulkaMessageEm.ViewRequest();
+ request.setExternalId(externalId);
+ var response = client.view(request);
+ return ResponseEntity.status(HttpStatus.OK).body(response);
}
}
diff --git a/app/sepuling-kotlin/src/it/kotlin/smecalculus/bezmen/messaging/SepulkaClientIT.kt b/app/sepuling-kotlin/src/it/kotlin/smecalculus/bezmen/messaging/SepulkaClientIT.kt
index 53636164..8a1d6143 100644
--- a/app/sepuling-kotlin/src/it/kotlin/smecalculus/bezmen/messaging/SepulkaClientIT.kt
+++ b/app/sepuling-kotlin/src/it/kotlin/smecalculus/bezmen/messaging/SepulkaClientIT.kt
@@ -17,6 +17,7 @@ import java.util.UUID
@ExtendWith(SpringExtension::class)
@ContextConfiguration(classes = [SepulkaClientBeans::class])
abstract class SepulkaClientIT {
+
@Autowired
private lateinit var externalClient: SepulkaClient
@@ -42,4 +43,24 @@ abstract class SepulkaClientIT {
.ignoringExpectedNullFields()
.isEqualTo(expectedResponse)
}
+
+ @Test
+ fun shouldViewSepulka() {
+ // given
+ val externalId = UUID.randomUUID().toString()
+ // and
+ val request = SepulkaMessageEmEg.viewRequest(externalId)
+ // and
+ whenever(serviceMock.view(any(SepulkaMessageDm.ViewRequest::class.java)))
+ .thenReturn(SepulkaMessageDmEg.viewResponse(externalId).build())
+ // and
+ val expectedResponse = SepulkaMessageEmEg.viewResponse(externalId)
+ // when
+ val actualResponse = externalClient.view(request)
+ // then
+ assertThat(actualResponse)
+ .usingRecursiveComparison()
+ .ignoringExpectedNullFields()
+ .isEqualTo(expectedResponse)
+ }
}
diff --git a/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/core/SepulkaServiceImpl.kt b/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/core/SepulkaServiceImpl.kt
index 8c8bb3bb..da53937d 100644
--- a/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/core/SepulkaServiceImpl.kt
+++ b/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/core/SepulkaServiceImpl.kt
@@ -1,9 +1,9 @@
package smecalculus.bezmen.core
-import smecalculus.bezmen.core.SepulkaMessageDm.PreviewRequest
-import smecalculus.bezmen.core.SepulkaMessageDm.PreviewResponse
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationRequest
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationResponse
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewRequest
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewResponse
import smecalculus.bezmen.storage.SepulkaDao
import java.time.LocalDateTime
import java.util.UUID
@@ -25,7 +25,7 @@ class SepulkaServiceImpl(
return converter.toMessage(sepulkaSaved).build()
}
- override fun view(request: PreviewRequest): List {
- return listOf()
+ override fun view(request: ViewRequest): ViewResponse {
+ return ViewResponse(request.externalId)
}
}
diff --git a/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/SepulkaClientImpl.kt b/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/SepulkaClientImpl.kt
index 4e1ed257..458c0937 100644
--- a/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/SepulkaClientImpl.kt
+++ b/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/SepulkaClientImpl.kt
@@ -3,6 +3,8 @@ package smecalculus.bezmen.messaging
import smecalculus.bezmen.core.SepulkaService
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse
import smecalculus.bezmen.validation.EdgeValidator
class SepulkaClientImpl(
@@ -16,4 +18,11 @@ class SepulkaClientImpl(
val response = service.register(request)
return mapper.toEdge(response)
}
+
+ override fun view(requestEdge: ViewRequest): ViewResponse {
+ validator.validate(requestEdge)
+ val request = mapper.toDomain(requestEdge)
+ val response = service.view(request)
+ return mapper.toEdge(response)
+ }
}
diff --git a/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/springmvc/SepulkaController.kt b/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/springmvc/SepulkaController.kt
index 598b6e17..18b458df 100644
--- a/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/springmvc/SepulkaController.kt
+++ b/app/sepuling-kotlin/src/main/kotlin/smecalculus/bezmen/messaging/springmvc/SepulkaController.kt
@@ -2,6 +2,8 @@ package smecalculus.bezmen.messaging.springmvc
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
@@ -9,6 +11,8 @@ import org.springframework.web.bind.annotation.RestController
import smecalculus.bezmen.messaging.SepulkaClient
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse
@RestController
@RequestMapping("sepulkas")
@@ -17,9 +21,19 @@ class SepulkaController(
) {
@PostMapping
fun register(
- @RequestBody requestEdge: RegistrationRequest,
+ @RequestBody request: RegistrationRequest,
): ResponseEntity {
- val responseEdge = client.register(requestEdge)
- return ResponseEntity.status(HttpStatus.CREATED).body(responseEdge)
+ val response = client.register(request)
+ return ResponseEntity.status(HttpStatus.CREATED).body(response)
+ }
+
+ @GetMapping("/{externalId}")
+ fun register(
+ @PathVariable("externalId") externalId: String,
+ ): ResponseEntity {
+ val request = ViewRequest()
+ request.externalId = externalId
+ val response = client.view(request)
+ return ResponseEntity.status(HttpStatus.OK).body(response)
}
}
diff --git a/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java b/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java
index 853767e5..4b5ff446 100644
--- a/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java
+++ b/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java
@@ -2,10 +2,14 @@
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse;
/**
* Port: client side
*/
public interface SepulkaClient {
RegistrationResponse register(RegistrationRequest request);
+
+ ViewResponse view(ViewRequest request);
}
diff --git a/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEm.java b/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEm.java
index c1c750c5..56bd1669 100644
--- a/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEm.java
+++ b/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEm.java
@@ -14,8 +14,23 @@ public static class RegistrationRequest {
@Data
public static class RegistrationResponse {
+ String externalId;
+ }
+
+ @Data
+ public static class SearchResponse {
+ String externalId;
+ }
+
+ @Data
+ public static class ViewRequest {
@NotNull
@Size(min = 1, max = 64)
String externalId;
}
+
+ @Data
+ public static class ViewResponse {
+ String externalId;
+ }
}
diff --git a/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEmEg.java b/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEmEg.java
index a0b6f020..9d0babd8 100644
--- a/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEmEg.java
+++ b/lib/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageEmEg.java
@@ -3,6 +3,8 @@
import java.util.UUID;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse;
public abstract class SepulkaMessageEmEg {
public static RegistrationRequest registrationRequest() {
@@ -28,4 +30,28 @@ public static RegistrationResponse registrationResponse(String externalId) {
responseEdge.setExternalId(externalId);
return responseEdge;
}
+
+ public static ViewRequest viewRequest() {
+ var requestEdge = new ViewRequest();
+ requestEdge.setExternalId(UUID.randomUUID().toString());
+ return requestEdge;
+ }
+
+ public static ViewRequest viewRequest(String id) {
+ var requestEdge = viewRequest();
+ requestEdge.setExternalId(id);
+ return requestEdge;
+ }
+
+ public static ViewResponse viewResponse() {
+ var responseEdge = new ViewResponse();
+ responseEdge.setExternalId(UUID.randomUUID().toString());
+ return responseEdge;
+ }
+
+ public static ViewResponse viewResponse(String externalId) {
+ var responseEdge = viewResponse();
+ responseEdge.setExternalId(externalId);
+ return responseEdge;
+ }
}
diff --git a/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDm.java b/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDm.java
index e0777a97..5e127cd7 100644
--- a/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDm.java
+++ b/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDm.java
@@ -11,8 +11,8 @@ public record RegistrationRequest(@NonNull String externalId) {}
public record RegistrationResponse(@NonNull String externalId) {}
@Builder
- public record PreviewRequest(@NonNull String externalId) {}
+ public record ViewRequest(@NonNull String externalId) {}
@Builder
- public record PreviewResponse(@NonNull String externalId) {}
+ public record ViewResponse(@NonNull String externalId) {}
}
diff --git a/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDmEg.java b/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDmEg.java
index febb5495..8f277c73 100644
--- a/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDmEg.java
+++ b/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaMessageDmEg.java
@@ -2,6 +2,7 @@
import java.util.UUID;
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationResponse;
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewResponse;
public class SepulkaMessageDmEg {
public static RegistrationResponse.Builder registrationResponse() {
@@ -11,4 +12,12 @@ public static RegistrationResponse.Builder registrationResponse() {
public static RegistrationResponse.Builder registrationResponse(String externalId) {
return registrationResponse().externalId(externalId);
}
+
+ public static ViewResponse.Builder viewResponse() {
+ return ViewResponse.builder().externalId(UUID.randomUUID().toString());
+ }
+
+ public static ViewResponse.Builder viewResponse(String externalId) {
+ return viewResponse().externalId(externalId);
+ }
}
diff --git a/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java b/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java
index c60e69a6..21766fad 100644
--- a/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java
+++ b/lib/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java
@@ -1,13 +1,12 @@
package smecalculus.bezmen.core;
-import java.util.List;
-import smecalculus.bezmen.core.SepulkaMessageDm.PreviewRequest;
-import smecalculus.bezmen.core.SepulkaMessageDm.PreviewResponse;
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationRequest;
import smecalculus.bezmen.core.SepulkaMessageDm.RegistrationResponse;
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewRequest;
+import smecalculus.bezmen.core.SepulkaMessageDm.ViewResponse;
public interface SepulkaService {
RegistrationResponse register(RegistrationRequest request);
- List view(PreviewRequest request);
+ ViewResponse view(ViewRequest request);
}
diff --git a/lib/essentials/pom.xml b/lib/essentials/pom.xml
index cc19bd93..4b4e9ca9 100644
--- a/lib/essentials/pom.xml
+++ b/lib/essentials/pom.xml
@@ -14,12 +14,17 @@
jar
-
+
${project.groupId}
abstraction
compile
+
+ ${project.groupId}
+ testing
+ test
+
com.fasterxml.jackson.core
diff --git a/lib/messaging-client/pom.xml b/lib/messaging-client/pom.xml
index 8d124ccf..d8ca932c 100644
--- a/lib/messaging-client/pom.xml
+++ b/lib/messaging-client/pom.xml
@@ -14,19 +14,21 @@
jar
-
${project.groupId}
abstraction-client
compile
-
com.fasterxml.jackson.core
jackson-databind
compile
-
+
+ org.slf4j
+ slf4j-api
+ compile
+
${project.groupId}
testing
diff --git a/lib/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java b/lib/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java
index 7d593192..552ee5dc 100644
--- a/lib/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java
+++ b/lib/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java
@@ -1,6 +1,5 @@
package smecalculus.bezmen.messaging;
-import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.URI;
@@ -13,6 +12,8 @@
import smecalculus.bezmen.configuration.ClientProps;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse;
@RequiredArgsConstructor
public class BezmenClientJavaHttp implements BezmenClient {
@@ -38,9 +39,29 @@ public RegistrationResponse register(RegistrationRequest request) {
.header("Accept", "application/json")
.build();
var httpResponse = client.send(httpRequest, BodyHandlers.ofString());
- return mapper.readValue(httpResponse.body(), RegistrationResponse.class);
- } catch (JsonProcessingException e) {
+ if (httpResponse.statusCode() < 300) {
+ return mapper.readValue(httpResponse.body(), RegistrationResponse.class);
+ }
+ throw new RuntimeException(httpResponse.body());
+ } catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public ViewResponse view(ViewRequest request) {
+ URI uri = URI.create("http://" + props.host() + ":" + props.port() + "/sepulkas/" + request.getExternalId());
+ try {
+ var httpRequest = HttpRequest.newBuilder()
+ .uri(uri)
+ .GET()
+ .header("Accept", "application/json")
+ .build();
+ var httpResponse = client.send(httpRequest, BodyHandlers.ofString());
+ if (httpResponse.statusCode() < 300) {
+ return mapper.readValue(httpResponse.body(), ViewResponse.class);
+ }
+ throw new RuntimeException(httpResponse.body());
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
diff --git a/lib/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java b/lib/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java
index 09dbb786..2b73eede 100644
--- a/lib/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java
+++ b/lib/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java
@@ -8,4 +8,8 @@ public interface SepulkaMessageMapper {
SepulkaMessageDm.RegistrationRequest toDomain(SepulkaMessageEm.RegistrationRequest request);
SepulkaMessageEm.RegistrationResponse toEdge(SepulkaMessageDm.RegistrationResponse response);
+
+ SepulkaMessageDm.ViewRequest toDomain(SepulkaMessageEm.ViewRequest request);
+
+ SepulkaMessageEm.ViewResponse toEdge(SepulkaMessageDm.ViewResponse response);
}
diff --git a/test/e2e/src/main/java/smecalculus/bezmen/construction/StandBeans.java b/test/e2e/src/main/java/smecalculus/bezmen/construction/StandBeans.java
index 1cab6e2d..73e80191 100644
--- a/test/e2e/src/main/java/smecalculus/bezmen/construction/StandBeans.java
+++ b/test/e2e/src/main/java/smecalculus/bezmen/construction/StandBeans.java
@@ -1,6 +1,12 @@
package smecalculus.bezmen.construction;
+import static com.fasterxml.jackson.core.JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION;
+
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.core.DefaultDockerClientConfig;
+import com.github.dockerjava.core.DockerClientImpl;
+import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import java.net.http.HttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -9,6 +15,7 @@
import smecalculus.bezmen.configuration.TestingProps;
import smecalculus.bezmen.messaging.BezmenClient;
import smecalculus.bezmen.messaging.BezmenClientJavaHttp;
+import smecalculus.bezmen.testing.Demiurge;
@Configuration(proxyBeanMethods = false)
public class StandBeans {
@@ -23,7 +30,23 @@ ClientProps clientProps(Environment environment) {
@Bean
BezmenClient bezmenClient(ClientProps clientProps) {
var jsonMapper = new ObjectMapper();
+ jsonMapper.enable(INCLUDE_SOURCE_IN_LOCATION);
var httpClient = HttpClient.newHttpClient();
return new BezmenClientJavaHttp(clientProps, jsonMapper, httpClient);
}
+
+ @Bean
+ DockerClient dockerClient() {
+ var clientConfig =
+ DefaultDockerClientConfig.createDefaultConfigBuilder().build();
+ var httpClient = new ApacheDockerHttpClient.Builder()
+ .dockerHost(clientConfig.getDockerHost())
+ .build();
+ return DockerClientImpl.getInstance(clientConfig, httpClient);
+ }
+
+ @Bean
+ Demiurge demiurge(DockerClient dockerClient) {
+ return new Demiurge(dockerClient);
+ }
}
diff --git a/test/e2e/src/test/java/smecalculus/bezmen/ToySuite.java b/test/e2e/src/test/java/smecalculus/bezmen/ResilienceSuite.java
similarity index 61%
rename from test/e2e/src/test/java/smecalculus/bezmen/ToySuite.java
rename to test/e2e/src/test/java/smecalculus/bezmen/ResilienceSuite.java
index 7c061d0f..34a0c736 100644
--- a/test/e2e/src/test/java/smecalculus/bezmen/ToySuite.java
+++ b/test/e2e/src/test/java/smecalculus/bezmen/ResilienceSuite.java
@@ -4,5 +4,5 @@
import org.junit.platform.suite.api.Suite;
@Suite
-@SelectPackages("smecalculus.bezmen.registration")
-public class ToySuite {}
+@SelectPackages("smecalculus.bezmen.resilience")
+public class ResilienceSuite {}
diff --git a/test/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java b/test/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java
index bbdb09e1..c0be9bb6 100644
--- a/test/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java
+++ b/test/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java
@@ -7,7 +7,6 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
@@ -40,16 +39,4 @@ void shouldRegisterSepulka() {
// then
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
}
-
- @Test
- @EnabledIfSystemProperty(named = "storage.protocol.mode", matches = "postgres")
- void postgresSpecificTest() {
- // empty
- }
-
- @Test
- @EnabledIfSystemProperty(named = "storage.protocol.mode", matches = "sqlite")
- void sqliteSpecificTest() {
- // empty
- }
}
diff --git a/test/e2e/src/test/java/smecalculus/bezmen/resilience/AbstractResilienceTest.java b/test/e2e/src/test/java/smecalculus/bezmen/resilience/AbstractResilienceTest.java
new file mode 100644
index 00000000..d19e3124
--- /dev/null
+++ b/test/e2e/src/test/java/smecalculus/bezmen/resilience/AbstractResilienceTest.java
@@ -0,0 +1,37 @@
+package smecalculus.bezmen.resilience;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.model.Container;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import smecalculus.bezmen.construction.StandBeans;
+import smecalculus.bezmen.testing.Demiurge;
+
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = StandBeans.class)
+public abstract class AbstractResilienceTest {
+
+ @Autowired
+ protected DockerClient dockerClient;
+
+ @Autowired
+ protected Demiurge demiurge;
+
+ protected Container postgresPrimary;
+ protected Container postgresSecondary;
+
+ @BeforeAll
+ void abstractBeforeAll() {
+ var containers = dockerClient.listContainersCmd().withShowAll(true).exec().stream()
+ .collect(toMap(container -> container.getNames()[0], identity()));
+ containers.values().forEach(demiurge::starts);
+ postgresPrimary = containers.get("/bezmen-postgres-primary");
+ postgresSecondary = containers.get("/bezmen-postgres-secondary");
+ }
+}
diff --git a/test/e2e/src/test/java/smecalculus/bezmen/resilience/SepulkaTest.java b/test/e2e/src/test/java/smecalculus/bezmen/resilience/SepulkaTest.java
new file mode 100644
index 00000000..ddf8b225
--- /dev/null
+++ b/test/e2e/src/test/java/smecalculus/bezmen/resilience/SepulkaTest.java
@@ -0,0 +1,43 @@
+package smecalculus.bezmen.resilience;
+
+import static java.time.Duration.ofSeconds;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+import static smecalculus.bezmen.messaging.SepulkaMessageEmEg.registrationRequest;
+import static smecalculus.bezmen.messaging.SepulkaMessageEmEg.viewRequest;
+
+import java.util.UUID;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import smecalculus.bezmen.messaging.BezmenClient;
+import smecalculus.bezmen.messaging.SepulkaMessageEmEg;
+
+public class SepulkaTest extends AbstractResilienceTest {
+
+ @Autowired
+ private BezmenClient bezmenClient;
+
+ @BeforeAll
+ void beforeAll() {
+ await("isReady").atMost(ofSeconds(5)).until(bezmenClient::isReady);
+ }
+
+ @Test
+ void shouldViewSepulka() {
+ // given
+ String externalId = UUID.randomUUID().toString();
+ // and
+ var registrationRequest = registrationRequest(externalId);
+ // and
+ bezmenClient.register(registrationRequest(externalId));
+ // and
+ demiurge.kills(postgresPrimary);
+ // and
+ var expectedResponse = SepulkaMessageEmEg.viewResponse(registrationRequest.getExternalId());
+ // when
+ var actualResponse = bezmenClient.view(viewRequest(externalId));
+ // then
+ assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
+ }
+}
diff --git a/test/e2e/src/test/resources/docker-java.properties b/test/e2e/src/test/resources/docker-java.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/tool/pom.xml b/tool/pom.xml
index b673420e..fd6ece70 100644
--- a/tool/pom.xml
+++ b/tool/pom.xml
@@ -37,6 +37,13 @@
lombok
${lombok.version}
+
+ com.github.docker-java
+ docker-java-bom
+ 3.3.6
+ import
+ pom
+
org.junit
junit-bom
@@ -63,6 +70,16 @@
import
pom
+
+ org.slf4j
+ slf4j-api
+ 2.0.12
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.16.1
+
jakarta.servlet
jakarta.servlet-api
diff --git a/tool/testing/pom.xml b/tool/testing/pom.xml
index 93818358..45e9e1c6 100644
--- a/tool/testing/pom.xml
+++ b/tool/testing/pom.xml
@@ -47,6 +47,17 @@
compile
+
+ com.github.docker-java
+ docker-java-core
+ compile
+
+
+ com.github.docker-java
+ docker-java-transport-httpclient5
+ compile
+
+
org.junit.jupiter
junit-jupiter-api
@@ -81,7 +92,7 @@
org.awaitility
awaitility
- runtime
+ compile
diff --git a/tool/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java b/tool/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java
index e56297ea..fd09a39e 100644
--- a/tool/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java
+++ b/tool/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java
@@ -6,6 +6,8 @@
import org.springframework.test.web.reactive.server.WebTestClient;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationRequest;
import smecalculus.bezmen.messaging.SepulkaMessageEm.RegistrationResponse;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewRequest;
+import smecalculus.bezmen.messaging.SepulkaMessageEm.ViewResponse;
@RequiredArgsConstructor
public class SepulkaClientSpringWebTest implements SepulkaClient {
@@ -25,4 +27,15 @@ public RegistrationResponse register(RegistrationRequest request) {
.returnResult()
.getResponseBody();
}
+
+ @Override
+ public ViewResponse view(ViewRequest request) {
+ return client.get()
+ .uri("/sepulkas/" + request.getExternalId())
+ .accept(MediaType.APPLICATION_JSON)
+ .exchange()
+ .expectBody(ViewResponse.class)
+ .returnResult()
+ .getResponseBody();
+ }
}
diff --git a/tool/testing/src/main/java/smecalculus/bezmen/testing/Demiurge.java b/tool/testing/src/main/java/smecalculus/bezmen/testing/Demiurge.java
new file mode 100644
index 00000000..087ae4c3
--- /dev/null
+++ b/tool/testing/src/main/java/smecalculus/bezmen/testing/Demiurge.java
@@ -0,0 +1,46 @@
+package smecalculus.bezmen.testing;
+
+import static org.awaitility.Awaitility.await;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.exception.NotModifiedException;
+import com.github.dockerjava.api.model.Container;
+import java.time.Duration;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@RequiredArgsConstructor
+public class Demiurge {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Demiurge.class);
+
+ @NonNull
+ private DockerClient dockerClient;
+
+ public void starts(@NonNull Container container) {
+ try {
+ dockerClient.startContainerCmd(container.getId()).exec();
+ await().atMost(Duration.ofSeconds(20)).until(() -> isStarted(container));
+ } catch (NotModifiedException e) {
+ LOG.debug("Already started");
+ }
+ }
+
+ public void kills(@NonNull Container container) {
+ dockerClient.killContainerCmd(container.getId()).exec();
+ }
+
+ private boolean isStarted(@NonNull Container container) {
+ var response = dockerClient.inspectContainerCmd(container.getId()).exec();
+ if (response.getConfig().getHealthcheck() == null) {
+ return Boolean.TRUE.equals(response.getState().getRunning());
+ }
+ var health = response.getState().getHealth();
+ if (health == null) {
+ return false;
+ }
+ return health.getStatus().equalsIgnoreCase("healthy");
+ }
+}