From 0c82dde6844376d006a07a1f619d885f08dcdea6 Mon Sep 17 00:00:00 2001 From: Pavel Vetokhin Date: Sat, 21 Oct 2023 14:01:19 +0300 Subject: [PATCH] Storage models (#175) --- .../bezmen/core/SepulkaServiceImpl.java | 24 ++++-- .../bezmen/messaging/SepulkaClientImpl.java | 4 +- .../springmvc/SepulkaController.java | 6 +- .../bezmen/storage/ContentionException.java | 3 + .../smecalculus/bezmen/storage/EdgeSide.java | 58 +++++++++++++ .../bezmen/storage/SepulkaDao.java | 16 ++-- .../bezmen/storage/SepulkaDaoMyBatis.java | 33 +++++--- .../bezmen/storage/SepulkaDaoSpringData.java | 36 ++++---- .../bezmen/storage/SepulkaEdge.java | 21 ----- .../bezmen/storage/SepulkaStateMapper.java | 17 +++- .../storage/mybatis/SepulkaSqlMapper.java | 67 ++++++++++----- .../storage/springdata/SepulkaRepository.java | 26 +++++- .../bezmen/construction/SepulkaDaoBeans.java | 83 +++++++------------ .../construction/StoragePropsBeans.java | 41 +++++++++ .../bezmen/messaging/SepulkaClientIT.java | 13 ++- .../bezmen/storage/SepulkaDaoIT.java | 51 ++++++++++-- .../bezmen/storage/SepulkaDaoMyBatisH2IT.java | 8 ++ .../storage/SepulkaDaoMyBatisPostgresIT.java | 4 +- .../bezmen/storage/SepulkaDaoMyBatisTest.java | 9 -- .../storage/SepulkaDaoSpringDataH2IT.java | 8 ++ .../SepulkaDaoSpringDataPostgresIT.java | 4 +- docs/solution.adoc | 6 +- .../bezmen/mapping/EdgeMapper.java | 5 ++ .../bezmen/messaging/EdgeSide.java | 22 +++++ .../bezmen/messaging/EdgeSideEg.java | 32 +++++++ .../bezmen/messaging/SepulkaClient.java | 8 +- .../messaging/SepulkaNewRequestEdge.java | 13 --- .../bezmen/messaging/SepulkaNewRequestEg.java | 19 ----- .../messaging/SepulkaNewResponseEdge.java | 13 --- .../messaging/SepulkaNewResponseEg.java | 19 ----- .../smecalculus/bezmen/core/ClientSide.java | 19 +++++ .../smecalculus/bezmen/core/ClientSideEg.java | 14 ++++ .../java/smecalculus/bezmen/core/Sepulka.java | 11 --- .../smecalculus/bezmen/core/SepulkaEg.java | 31 ------- .../bezmen/core/SepulkaNewRequest.java | 10 --- .../bezmen/core/SepulkaNewRequestEg.java | 17 ---- .../bezmen/core/SepulkaNewResponse.java | 10 --- .../bezmen/core/SepulkaNewResponseEg.java | 21 ----- .../bezmen/core/SepulkaService.java | 8 +- .../bezmen/core/SepulkaSliceMapper.java | 7 +- .../smecalculus/bezmen/core/ServerSide.java | 25 ++++++ .../smecalculus/bezmen/core/ServerSideEg.java | 33 ++++++++ .../validation/ValidationPropsMapper.java | 3 +- .../messaging/BezmenClientJavaHttp.java | 6 +- .../configuration/MessagingPropsMapper.java | 3 +- .../messaging/SepulkaMessageMapper.java | 10 +-- libs/pom.xml | 8 +- .../configuration/StateMappingPropsEg.java | 4 + .../bezmen/configuration/StoragePropsEg.java | 6 ++ .../configuration/StoragePropsMapper.java | 3 +- .../configuration/StorageProtocolPropsEg.java | 4 + .../construction/MappingMyBatisBeans.java | 2 + .../construction/MappingSpringDataBeans.java | 32 +++++-- .../bezmen/construction/StorageBeans.java | 10 +-- .../storage/mybatis/UuidTypeHandler.java | 42 ++++++++++ .../messaging/SepulkaClientSpringWebTest.java | 6 +- schemas/h2/sepulkarium/create.sql | 8 +- .../postgres/sepulkarium/owner/sepulkas.sql | 8 +- tests/e2e/pom.xml | 1 + .../bezmen/registration/SepulkaTest.java | 7 +- tests/pom.xml | 7 -- tools/pom.xml | 2 +- 62 files changed, 656 insertions(+), 391 deletions(-) create mode 100644 apps/sepuling/src/main/java/smecalculus/bezmen/storage/ContentionException.java create mode 100644 apps/sepuling/src/main/java/smecalculus/bezmen/storage/EdgeSide.java delete mode 100644 apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaEdge.java create mode 100644 apps/sepuling/src/test/java/smecalculus/bezmen/construction/StoragePropsBeans.java create mode 100644 apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisH2IT.java delete mode 100644 apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisTest.java create mode 100644 apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataH2IT.java create mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/mapping/EdgeMapper.java create mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSide.java create mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSideEg.java delete mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEdge.java delete mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEg.java delete mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEdge.java delete mode 100644 libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEg.java create mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSide.java create mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSideEg.java delete mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/Sepulka.java delete mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaEg.java delete mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequest.java delete mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequestEg.java delete mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponse.java delete mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponseEg.java create mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSide.java create mode 100644 libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSideEg.java create mode 100644 libs/storage/src/main/java/smecalculus/bezmen/storage/mybatis/UuidTypeHandler.java diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java b/apps/sepuling/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java index aeb36cb5..496df4e4 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/core/SepulkaServiceImpl.java @@ -2,9 +2,15 @@ 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.ClientSide.PreviewRequest; +import smecalculus.bezmen.core.ClientSide.PreviewResponse; +import smecalculus.bezmen.core.ClientSide.RegistrationRequest; +import smecalculus.bezmen.core.ClientSide.RegistrationResponse; import smecalculus.bezmen.storage.SepulkaDao; @RequiredArgsConstructor @@ -17,14 +23,20 @@ public class SepulkaServiceImpl implements SepulkaService { private SepulkaDao dao; @Override - public SepulkaNewResponse register(SepulkaNewRequest request) { - var sepulkaCreated = mapper.toEntity(request).internalId(randomUUID()).build(); - var sepulkaSaved = dao.save(sepulkaCreated); - return mapper.toSlice(sepulkaSaved); + public RegistrationResponse register(RegistrationRequest request) { + var now = LocalDateTime.now(); + var sepulkaCreated = mapper.toServer(request) + .internalId(randomUUID()) + .revision(0) + .createdAt(now) + .updatedAt(now) + .build(); + var sepulkaSaved = dao.add(sepulkaCreated); + return mapper.toClient(sepulkaSaved).build(); } @Override - public List getSepulkas() { - return dao.getSepulkas(); + public List view(PreviewRequest request) { + return Collections.emptyList(); } } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java b/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java index 9f1a47ce..9dba0f6d 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/SepulkaClientImpl.java @@ -3,6 +3,8 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import smecalculus.bezmen.core.SepulkaService; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationRequest; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationResponse; import smecalculus.bezmen.validation.EdgeValidator; @RequiredArgsConstructor @@ -18,7 +20,7 @@ public class SepulkaClientImpl implements SepulkaClient { private SepulkaService service; @Override - public SepulkaNewResponseEdge register(SepulkaNewRequestEdge requestEdge) { + public RegistrationResponse register(RegistrationRequest requestEdge) { validator.validate(requestEdge); var request = mapper.toDomain(requestEdge); var response = service.register(request); diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java b/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java index c9b877ff..42435b47 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/messaging/springmvc/SepulkaController.java @@ -8,9 +8,9 @@ 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.EdgeSide.RegistrationRequest; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationResponse; import smecalculus.bezmen.messaging.SepulkaClient; -import smecalculus.bezmen.messaging.SepulkaNewRequestEdge; -import smecalculus.bezmen.messaging.SepulkaNewResponseEdge; @RestController @RequestMapping("sepulkas") @@ -21,7 +21,7 @@ public class SepulkaController { private SepulkaClient client; @PostMapping - ResponseEntity register(@RequestBody SepulkaNewRequestEdge requestEdge) { + ResponseEntity register(@RequestBody RegistrationRequest requestEdge) { var responseEdge = client.register(requestEdge); return ResponseEntity.status(HttpStatus.CREATED).body(responseEdge); } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/ContentionException.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/ContentionException.java new file mode 100644 index 00000000..c14e143d --- /dev/null +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/ContentionException.java @@ -0,0 +1,3 @@ +package smecalculus.bezmen.storage; + +public class ContentionException extends RuntimeException {} diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/EdgeSide.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/EdgeSide.java new file mode 100644 index 00000000..27db18b8 --- /dev/null +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/EdgeSide.java @@ -0,0 +1,58 @@ +package smecalculus.bezmen.storage; + +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.domain.Persistable; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +public abstract class EdgeSide { + + @Data + public static class ExistenceState { + UUID internalId; + } + + @Data + public static class PreviewState { + String externalId; + LocalDateTime createdAt; + } + + @Data + public static class TouchState { + Integer revision; + LocalDateTime updatedAt; + } + + @Data + @Table("sepulkas") + public static class AggregateState implements Persistable { + @Id + UUID internalId; + + @Column + String externalId; + + @Column + Integer revision; + + @Column + LocalDateTime createdAt; + + @Column + LocalDateTime updatedAt; + + @Override + public UUID getId() { + return internalId; + } + + @Override + public boolean isNew() { + return true; + } + } +} diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDao.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDao.java index 29e32e3c..18bbacf5 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDao.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDao.java @@ -1,18 +1,22 @@ package smecalculus.bezmen.storage; -import java.util.List; import java.util.Optional; import java.util.UUID; -import smecalculus.bezmen.core.Sepulka; +import smecalculus.bezmen.core.ServerSide.AggregateState; +import smecalculus.bezmen.core.ServerSide.ExistenceState; +import smecalculus.bezmen.core.ServerSide.PreviewState; +import smecalculus.bezmen.core.ServerSide.TouchState; /** - * Server side interface + * Port: server side */ public interface SepulkaDao { - Optional getById(UUID id); + AggregateState add(AggregateState state); - Sepulka save(Sepulka sepulka); + Optional getBy(String externalId); - List getSepulkas(); + Optional getBy(UUID internalId); + + void updateBy(TouchState state, UUID internalId); } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoMyBatis.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoMyBatis.java index 924ad173..123462be 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoMyBatis.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoMyBatis.java @@ -1,13 +1,13 @@ package smecalculus.bezmen.storage; -import static java.util.stream.Collectors.toList; - -import java.util.List; import java.util.Optional; import java.util.UUID; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import smecalculus.bezmen.core.Sepulka; +import smecalculus.bezmen.core.ServerSide.AggregateState; +import smecalculus.bezmen.core.ServerSide.ExistenceState; +import smecalculus.bezmen.core.ServerSide.PreviewState; +import smecalculus.bezmen.core.ServerSide.TouchState; import smecalculus.bezmen.storage.mybatis.SepulkaSqlMapper; @RequiredArgsConstructor @@ -20,19 +20,28 @@ public class SepulkaDaoMyBatis implements SepulkaDao { private SepulkaSqlMapper sqlMapper; @Override - public Optional getById(@NonNull UUID internalId) { - return sqlMapper.findById(internalId.toString()).map(stateMapper::toDomain); + public AggregateState add(@NonNull AggregateState state) { + var stateEdge = stateMapper.toEdge(state); + sqlMapper.insert(stateEdge); + return state; + } + + @Override + public Optional getBy(@NonNull String externalId) { + return sqlMapper.findByExternalId(externalId).map(stateMapper::toDomain); } @Override - public Sepulka save(@NonNull Sepulka sepulka) { - var sepulkaEdge = stateMapper.toEdge(sepulka); - sqlMapper.insert(sepulkaEdge); - return sepulka; + public Optional getBy(@NonNull UUID internalId) { + return sqlMapper.findByInternalId(internalId.toString()).map(stateMapper::toDomain); } @Override - public List getSepulkas() { - return sqlMapper.selectAll().stream().map(stateMapper::toDomain).collect(toList()); + public void updateBy(TouchState state, UUID internalId) { + var stateEdge = stateMapper.toEdge(state); + var matchedCount = sqlMapper.updateBy(stateEdge, internalId.toString()); + if (matchedCount == 0) { + throw new ContentionException(); + } } } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoSpringData.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoSpringData.java index c2f46643..47045274 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoSpringData.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaDaoSpringData.java @@ -1,14 +1,10 @@ package smecalculus.bezmen.storage; -import static java.util.stream.Collectors.toList; -import static java.util.stream.StreamSupport.stream; - -import java.util.List; import java.util.Optional; import java.util.UUID; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import smecalculus.bezmen.core.Sepulka; +import smecalculus.bezmen.core.ServerSide; import smecalculus.bezmen.storage.springdata.SepulkaRepository; @RequiredArgsConstructor @@ -21,21 +17,31 @@ public class SepulkaDaoSpringData implements SepulkaDao { private SepulkaRepository repository; @Override - public Optional getById(@NonNull UUID id) { - return repository.findById(id.toString()).map(mapper::toDomain); + public ServerSide.AggregateState add(@NonNull ServerSide.AggregateState state) { + var stateEdge = repository.save(mapper.toEdge(state)); + return mapper.toDomain(stateEdge); + } + + @Override + public Optional getBy(@NonNull String externalId) { + return repository + .findByExternalId(externalId, EdgeSide.ExistenceState.class) + .map(mapper::toDomain); } @Override - public Sepulka save(@NonNull Sepulka sepulka) { - var newSepulkaEdge = mapper.toEdge(sepulka); - var savedSepulkaEdge = repository.save(newSepulkaEdge); - return mapper.toDomain(savedSepulkaEdge); + public Optional getBy(@NonNull UUID internalId) { + return repository + .findByInternalId(internalId.toString(), EdgeSide.PreviewState.class) + .map(mapper::toDomain); } @Override - public List getSepulkas() { - return stream(repository.findAll().spliterator(), false) - .map(mapper::toDomain) - .collect(toList()); + public void updateBy(ServerSide.TouchState state, UUID internalId) { + var stateEdge = mapper.toEdge(state); + var matchedCount = repository.updateBy(stateEdge, internalId.toString()); + if (matchedCount == 0) { + throw new ContentionException(); + } } } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaEdge.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaEdge.java deleted file mode 100644 index 3840553f..00000000 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaEdge.java +++ /dev/null @@ -1,21 +0,0 @@ -package smecalculus.bezmen.storage; - -import lombok.Data; -import org.springframework.data.annotation.Id; -import org.springframework.data.annotation.Version; -import org.springframework.data.relational.core.mapping.Table; - -/** - * Model: edge entity - */ -@Data -@Table("sepulkas") -public class SepulkaEdge { - @Id - String internalId; - - String externalId; - - @Version - Integer version; -} diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaStateMapper.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaStateMapper.java index 4a8c2788..766b6f07 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaStateMapper.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/SepulkaStateMapper.java @@ -1,11 +1,20 @@ package smecalculus.bezmen.storage; import org.mapstruct.Mapper; -import smecalculus.bezmen.core.Sepulka; +import smecalculus.bezmen.core.ServerSide; +import smecalculus.bezmen.mapping.EdgeMapper; @Mapper -public interface SepulkaStateMapper { - SepulkaEdge toEdge(Sepulka sepulka); +public interface SepulkaStateMapper extends EdgeMapper { + EdgeSide.AggregateState toEdge(ServerSide.AggregateState state); - Sepulka toDomain(SepulkaEdge sepulkaEdge); + ServerSide.AggregateState toDomain(EdgeSide.AggregateState state); + + EdgeSide.TouchState toEdge(ServerSide.TouchState state); + + ServerSide.ExistenceState toDomain(EdgeSide.ExistenceState state); + + EdgeSide.PreviewState toEdge(ServerSide.PreviewState state); + + ServerSide.PreviewState toDomain(EdgeSide.PreviewState state); } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/mybatis/SepulkaSqlMapper.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/mybatis/SepulkaSqlMapper.java index e5800bc2..3be87324 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/mybatis/SepulkaSqlMapper.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/mybatis/SepulkaSqlMapper.java @@ -1,39 +1,62 @@ package smecalculus.bezmen.storage.mybatis; -import java.util.List; import java.util.Optional; import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; -import smecalculus.bezmen.storage.SepulkaEdge; +import org.apache.ibatis.annotations.Update; +import smecalculus.bezmen.storage.EdgeSide.AggregateState; +import smecalculus.bezmen.storage.EdgeSide.ExistenceState; +import smecalculus.bezmen.storage.EdgeSide.PreviewState; +import smecalculus.bezmen.storage.EdgeSide.TouchState; public interface SepulkaSqlMapper { @Insert( """ - INSERT INTO sepulkas ( - internal_id, - external_id, - version - ) - VALUES ( - #{internalId}, - #{externalId}, - #{version} - ) + INSERT INTO sepulkas ( + internal_id, + external_id, + revision, + created_at, + updated_at + ) + VALUES ( + #{internalId}, + #{externalId}, + #{revision}, + #{createdAt}, + #{updatedAt} + ) """) - void insert(SepulkaEdge sepulkaEdge); + void insert(AggregateState state); @Select( """ - SELECT - internal_id as internalId, - external_id as externalId, - version - FROM sepulkas - WHERE internal_id = #{internalId} + SELECT + internal_id as internalId + FROM sepulkas + WHERE external_id = #{externalId} """) - Optional findById(String internalId); + Optional findByExternalId(String externalId); - @Select("SELECT * FROM sepulkas") - List selectAll(); + @Select( + """ + SELECT + external_id as externalId, + created_at as createdAt + FROM sepulkas + WHERE internal_id = #{internalId} + """) + Optional findByInternalId(String internalId); + + @Update( + """ + UPDATE sepulkas + SET revision = revision + 1, + updated_at = #{state.updatedAt} + WHERE internal_id = #{id} + AND revision = #{state.revision} + """) + int updateBy(@Param("state") TouchState state, @Param("id") String internalId); } diff --git a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/springdata/SepulkaRepository.java b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/springdata/SepulkaRepository.java index 04e5bfc6..42159b9e 100644 --- a/apps/sepuling/src/main/java/smecalculus/bezmen/storage/springdata/SepulkaRepository.java +++ b/apps/sepuling/src/main/java/smecalculus/bezmen/storage/springdata/SepulkaRepository.java @@ -1,6 +1,28 @@ package smecalculus.bezmen.storage.springdata; +import java.util.Optional; +import org.springframework.data.jdbc.repository.query.Modifying; +import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.repository.CrudRepository; -import smecalculus.bezmen.storage.SepulkaEdge; +import org.springframework.data.repository.query.Param; +import org.springframework.lang.Nullable; +import smecalculus.bezmen.storage.EdgeSide.AggregateState; +import smecalculus.bezmen.storage.EdgeSide.TouchState; -public interface SepulkaRepository extends CrudRepository {} +public interface SepulkaRepository extends CrudRepository { + + Optional findByExternalId(@Nullable String externalId, Class type); + + Optional findByInternalId(@Nullable String internalId, Class type); + + @Modifying + @Query( + """ + UPDATE sepulkas + SET revision = revision + 1, + updated_at = :#{#state.updatedAt} + WHERE internal_id = :id + AND revision = :#{#state.revision} + """) + int updateBy(@Param("state") TouchState state, @Param("id") String internalId); +} diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/construction/SepulkaDaoBeans.java b/apps/sepuling/src/test/java/smecalculus/bezmen/construction/SepulkaDaoBeans.java index fe3fe17c..be47a817 100644 --- a/apps/sepuling/src/test/java/smecalculus/bezmen/construction/SepulkaDaoBeans.java +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/construction/SepulkaDaoBeans.java @@ -1,21 +1,16 @@ package smecalculus.bezmen.construction; import static java.util.stream.Collectors.joining; -import static smecalculus.bezmen.configuration.StateMappingMode.MY_BATIS; -import static smecalculus.bezmen.configuration.StateMappingMode.SPRING_DATA; -import static smecalculus.bezmen.configuration.StorageProtocolMode.POSTGRES; import java.util.Collection; import java.util.List; import java.util.stream.Stream; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import smecalculus.bezmen.configuration.StateMappingProps; import smecalculus.bezmen.configuration.StorageProps; -import smecalculus.bezmen.configuration.StorageProtocolProps; import smecalculus.bezmen.storage.SepulkaDao; import smecalculus.bezmen.storage.SepulkaDaoMyBatis; import smecalculus.bezmen.storage.SepulkaDaoSpringData; @@ -24,71 +19,49 @@ import smecalculus.bezmen.storage.mybatis.SepulkaSqlMapper; import smecalculus.bezmen.storage.springdata.SepulkaRepository; -@Configuration(proxyBeanMethods = false) public class SepulkaDaoBeans { public static final String DB = "testdb"; - @Bean - public DataSource dataSource(StorageProps storageProps) { - var common = List.of("DB_CLOSE_DELAY=-1"); - var specific = - switch (storageProps.protocolProps().protocolMode()) { - case H2 -> List.of("MODE=STRICT"); - case POSTGRES -> List.of("MODE=PostgreSQL", "DATABASE_TO_LOWER=TRUE", "DEFAULT_NULL_ORDERING=HIGH"); - }; - var nameWithSettings = Stream.of(List.of(DB), common, specific) - .flatMap(Collection::stream) - .collect(joining(";")); - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .setName(nameWithSettings) - .addScript("/schemas/sepulkarium/drop.sql") - .addScript("/schemas/sepulkarium/create.sql") - .build(); - } - - @Bean - public SepulkaStateMapper sepulkaStateMapper() { - return new SepulkaStateMapperImpl(); - } - - @Configuration(proxyBeanMethods = false) - public static class SpringDataPostgres { - + @Import(MappingSpringDataBeans.class) + public static class SpringData { @Bean - public SepulkaDao underTest(SepulkaStateMapper mapper, SepulkaRepository repository) { + public SepulkaDao sepulkaDao(SepulkaStateMapper mapper, SepulkaRepository repository) { return new SepulkaDaoSpringData(mapper, repository); } + } + @Import(MappingMyBatisBeans.class) + public static class MyBatis { @Bean - public StorageProps storageProps() { - return StorageProps.builder() - .mappingProps( - StateMappingProps.builder().mappingMode(SPRING_DATA).build()) - .protocolProps(StorageProtocolProps.builder() - .protocolMode(POSTGRES) - .build()) - .build(); + public SepulkaDao sepulkaDao(SepulkaStateMapper stateMapper, SepulkaSqlMapper sqlMapper) { + return new SepulkaDaoMyBatis(stateMapper, sqlMapper); } } - @Configuration(proxyBeanMethods = false) - public static class MyBatisPostgres { - + public static class Anyone { @Bean - public SepulkaDao underTest(SepulkaStateMapper stateMapper, SepulkaSqlMapper sqlMapper) { - return new SepulkaDaoMyBatis(stateMapper, sqlMapper); + public SepulkaStateMapper sepulkaStateMapper() { + return new SepulkaStateMapperImpl(); } @Bean - public StorageProps storageProps() { - return StorageProps.builder() - .mappingProps( - StateMappingProps.builder().mappingMode(MY_BATIS).build()) - .protocolProps(StorageProtocolProps.builder() - .protocolMode(POSTGRES) - .build()) + public DataSource dataSource(StorageProps storageProps) { + var common = List.of("DB_CLOSE_DELAY=-1"); + var specific = + switch (storageProps.protocolProps().protocolMode()) { + case H2 -> List.of("MODE=STRICT"); + case POSTGRES -> List.of( + "MODE=PostgreSQL", "DATABASE_TO_LOWER=TRUE", "DEFAULT_NULL_ORDERING=HIGH"); + }; + var nameWithSettings = Stream.of(List.of(DB), common, specific) + .flatMap(Collection::stream) + .collect(joining(";")); + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .setName(nameWithSettings) + .addScript("/schemas/sepulkarium/drop.sql") + .addScript("/schemas/sepulkarium/create.sql") .build(); } } diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/construction/StoragePropsBeans.java b/apps/sepuling/src/test/java/smecalculus/bezmen/construction/StoragePropsBeans.java new file mode 100644 index 00000000..7a35cf3f --- /dev/null +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/construction/StoragePropsBeans.java @@ -0,0 +1,41 @@ +package smecalculus.bezmen.construction; + +import static smecalculus.bezmen.configuration.StateMappingMode.MY_BATIS; +import static smecalculus.bezmen.configuration.StateMappingMode.SPRING_DATA; +import static smecalculus.bezmen.configuration.StorageProtocolMode.H2; +import static smecalculus.bezmen.configuration.StorageProtocolMode.POSTGRES; + +import org.springframework.context.annotation.Bean; +import smecalculus.bezmen.configuration.StorageProps; +import smecalculus.bezmen.configuration.StoragePropsEg; + +public class StoragePropsBeans { + + public static class SpringDataPostgres { + @Bean + public StorageProps storageProps() { + return StoragePropsEg.storageProps(SPRING_DATA, POSTGRES).build(); + } + } + + public static class SpringDataH2 { + @Bean + public StorageProps storageProps() { + return StoragePropsEg.storageProps(SPRING_DATA, H2).build(); + } + } + + public static class MyBatisPostgres { + @Bean + public StorageProps storageProps() { + return StoragePropsEg.storageProps(MY_BATIS, POSTGRES).build(); + } + } + + public static class MyBatisH2 { + @Bean + public StorageProps storageProps() { + return StoragePropsEg.storageProps(MY_BATIS, H2).build(); + } + } +} diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/messaging/SepulkaClientIT.java b/apps/sepuling/src/test/java/smecalculus/bezmen/messaging/SepulkaClientIT.java index faf172ec..bb3093cf 100644 --- a/apps/sepuling/src/test/java/smecalculus/bezmen/messaging/SepulkaClientIT.java +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/messaging/SepulkaClientIT.java @@ -3,9 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; -import static smecalculus.bezmen.core.SepulkaNewResponseEg.Pojos.sepulkaNewResponse; -import static smecalculus.bezmen.messaging.SepulkaNewRequestEg.Pojos.sepulkaNewRequestEdge; -import static smecalculus.bezmen.messaging.SepulkaNewResponseEg.Pojos.sepulkaNewResponseEdge; import java.util.UUID; import org.junit.jupiter.api.Test; @@ -14,7 +11,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import smecalculus.bezmen.construction.SepulkaClientBeans; -import smecalculus.bezmen.core.SepulkaNewRequest; +import smecalculus.bezmen.core.ClientSide.RegistrationRequest; +import smecalculus.bezmen.core.ClientSideEg; import smecalculus.bezmen.core.SepulkaService; @ExtendWith(SpringExtension.class) @@ -32,11 +30,12 @@ void shouldRegisterSepulka() { // given var externalId = UUID.randomUUID().toString(); // and - var request = sepulkaNewRequestEdge(externalId); + var request = EdgeSideEg.registrationRequest(externalId); // and - when(serviceMock.register(any(SepulkaNewRequest.class))).thenReturn(sepulkaNewResponse(externalId)); + when(serviceMock.register(any(RegistrationRequest.class))) + .thenReturn(ClientSideEg.registrationResponse(externalId).build()); // and - var expectedResponse = sepulkaNewResponseEdge(externalId); + var expectedResponse = EdgeSideEg.registrationResponse(externalId); // when var actualResponse = externalClient.register(request); // then diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoIT.java b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoIT.java index 61e8db15..45dff005 100644 --- a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoIT.java +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoIT.java @@ -1,18 +1,20 @@ package smecalculus.bezmen.storage; import static org.assertj.core.api.Assertions.assertThat; -import static smecalculus.bezmen.core.SepulkaEg.Pojos.sepulka; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.context.junit.jupiter.SpringExtension; import smecalculus.bezmen.construction.SepulkaDaoBeans; +import smecalculus.bezmen.core.ServerSideEg; +@DirtiesContext @ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = SepulkaDaoBeans.class) +@ContextConfiguration(classes = SepulkaDaoBeans.Anyone.class) @Sql("/schemas/sepulkarium/truncate.sql") abstract class SepulkaDaoIT { @@ -20,16 +22,49 @@ abstract class SepulkaDaoIT { private SepulkaDao sepulkaDao; @Test - void shouldSaveOneSepulka() { + void shouldAddOneSepulka() { // given - var expectedSepulka = sepulka(); + var expected1 = ServerSideEg.aggregateState().build(); + // and + var expected2 = + ServerSideEg.creationState().internalId(expected1.internalId()).build(); // when - var actualSepulka1 = sepulkaDao.save(expectedSepulka); + var actualSaved = sepulkaDao.add(expected1); + // and + var actualSelected = sepulkaDao.getBy(expected1.externalId()); + // then + assertThat(actualSaved).usingRecursiveComparison().isEqualTo(expected1); + // and + assertThat(actualSelected).contains(expected2); + } + + @Test + void shouldViewOneSepulka() { + // given + var aggregate = ServerSideEg.aggregateState().build(); + // and + sepulkaDao.add(aggregate); // and - var actualSepulka2 = sepulkaDao.getById(expectedSepulka.internalId()); + var expected = ServerSideEg.previewState(aggregate).build(); + // when + var actual = sepulkaDao.getBy(aggregate.internalId()); // then - assertThat(actualSepulka1).isEqualTo(expectedSepulka); + assertThat(actual).contains(expected); + } + + @Test + void shouldUpdateOneSepulka() { + // given + var aggregate = ServerSideEg.aggregateState().build(); // and - assertThat(actualSepulka2).contains(expectedSepulka); + sepulkaDao.add(aggregate); + // and + var updatedAt = aggregate.updatedAt().plusSeconds(1); + // and + var touch = ServerSideEg.touchState(aggregate).updatedAt(updatedAt).build(); + // when + sepulkaDao.updateBy(touch, aggregate.internalId()); + // then + // no exception } } diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisH2IT.java b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisH2IT.java new file mode 100644 index 00000000..be5910d4 --- /dev/null +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisH2IT.java @@ -0,0 +1,8 @@ +package smecalculus.bezmen.storage; + +import org.springframework.test.context.ContextConfiguration; +import smecalculus.bezmen.construction.SepulkaDaoBeans; +import smecalculus.bezmen.construction.StoragePropsBeans; + +@ContextConfiguration(classes = {StoragePropsBeans.MyBatisH2.class, SepulkaDaoBeans.MyBatis.class}) +public class SepulkaDaoMyBatisH2IT extends SepulkaDaoIT {} diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisPostgresIT.java b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisPostgresIT.java index 31aac61e..09ab05b6 100644 --- a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisPostgresIT.java +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisPostgresIT.java @@ -1,8 +1,8 @@ package smecalculus.bezmen.storage; import org.springframework.test.context.ContextConfiguration; -import smecalculus.bezmen.construction.MappingMyBatisBeans; import smecalculus.bezmen.construction.SepulkaDaoBeans; +import smecalculus.bezmen.construction.StoragePropsBeans; -@ContextConfiguration(classes = {SepulkaDaoBeans.MyBatisPostgres.class, MappingMyBatisBeans.class}) +@ContextConfiguration(classes = {StoragePropsBeans.MyBatisPostgres.class, SepulkaDaoBeans.MyBatis.class}) public class SepulkaDaoMyBatisPostgresIT extends SepulkaDaoIT {} diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisTest.java b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisTest.java deleted file mode 100644 index 3536c60f..00000000 --- a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoMyBatisTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package smecalculus.bezmen.storage; - -import org.junit.jupiter.api.Test; - -class SepulkaDaoMyBatisTest { - - @Test - void foo() {} -} diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataH2IT.java b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataH2IT.java new file mode 100644 index 00000000..d97c067b --- /dev/null +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataH2IT.java @@ -0,0 +1,8 @@ +package smecalculus.bezmen.storage; + +import org.springframework.test.context.ContextConfiguration; +import smecalculus.bezmen.construction.SepulkaDaoBeans; +import smecalculus.bezmen.construction.StoragePropsBeans; + +@ContextConfiguration(classes = {StoragePropsBeans.SpringDataH2.class, SepulkaDaoBeans.SpringData.class}) +public class SepulkaDaoSpringDataH2IT extends SepulkaDaoIT {} diff --git a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataPostgresIT.java b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataPostgresIT.java index 386a603a..a265e16b 100644 --- a/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataPostgresIT.java +++ b/apps/sepuling/src/test/java/smecalculus/bezmen/storage/SepulkaDaoSpringDataPostgresIT.java @@ -1,8 +1,8 @@ package smecalculus.bezmen.storage; import org.springframework.test.context.ContextConfiguration; -import smecalculus.bezmen.construction.MappingSpringDataBeans; import smecalculus.bezmen.construction.SepulkaDaoBeans; +import smecalculus.bezmen.construction.StoragePropsBeans; -@ContextConfiguration(classes = {SepulkaDaoBeans.SpringDataPostgres.class, MappingSpringDataBeans.class}) +@ContextConfiguration(classes = {StoragePropsBeans.SpringDataPostgres.class, SepulkaDaoBeans.SpringData.class}) public class SepulkaDaoSpringDataPostgresIT extends SepulkaDaoIT {} diff --git a/docs/solution.adoc b/docs/solution.adoc index e2437769..625b303b 100644 --- a/docs/solution.adoc +++ b/docs/solution.adoc @@ -98,10 +98,10 @@ image::solution/core.png[] === Модели и мапперы (models & mappers) [discrete] -====== Модели делим по двум основаниям +====== Модели делим по нескольким основаниям -. Предметные (domain) против пограничных (edge) -. Сущности (entities) против срезов (slices) +. Предметные (domain side) и пограничные (edge side) +. Клиентские (client side) и серверные (server side) === Клиенты и серверы (clients & servers) diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/mapping/EdgeMapper.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/mapping/EdgeMapper.java new file mode 100644 index 00000000..5349e64a --- /dev/null +++ b/libs/abstraction-client/src/main/java/smecalculus/bezmen/mapping/EdgeMapper.java @@ -0,0 +1,5 @@ +package smecalculus.bezmen.mapping; + +public interface EdgeMapper { + // nothing here yet +} diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSide.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSide.java new file mode 100644 index 00000000..cfac3ea8 --- /dev/null +++ b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSide.java @@ -0,0 +1,22 @@ +package smecalculus.bezmen.messaging; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +public class EdgeSide { + + @Data + public static class RegistrationRequest { + @NotNull + @Size(min = 1, max = 64) + String externalId; + } + + @Data + public static class RegistrationResponse { + @NotNull + @Size(min = 1, max = 64) + String externalId; + } +} diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSideEg.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSideEg.java new file mode 100644 index 00000000..159f81ff --- /dev/null +++ b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/EdgeSideEg.java @@ -0,0 +1,32 @@ +package smecalculus.bezmen.messaging; + +import java.util.UUID; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationRequest; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationResponse; + +public class EdgeSideEg { + + public static RegistrationRequest registrationRequest() { + var requestEdge = new RegistrationRequest(); + requestEdge.setExternalId(UUID.randomUUID().toString()); + return requestEdge; + } + + public static RegistrationRequest registrationRequest(String id) { + var requestEdge = registrationRequest(); + requestEdge.setExternalId(id); + return requestEdge; + } + + public static RegistrationResponse registrationResponse() { + var responseEdge = new EdgeSide.RegistrationResponse(); + responseEdge.setExternalId(UUID.randomUUID().toString()); + return responseEdge; + } + + public static EdgeSide.RegistrationResponse registrationResponse(String externalId) { + var responseEdge = registrationResponse(); + responseEdge.setExternalId(externalId); + return responseEdge; + } +} diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java index b0dfb11c..a786ed27 100644 --- a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java +++ b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaClient.java @@ -1,5 +1,11 @@ package smecalculus.bezmen.messaging; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationRequest; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationResponse; + +/** + * Port: client side + */ public interface SepulkaClient { - SepulkaNewResponseEdge register(SepulkaNewRequestEdge request); + RegistrationResponse register(RegistrationRequest request); } diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEdge.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEdge.java deleted file mode 100644 index d9d20e7d..00000000 --- a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEdge.java +++ /dev/null @@ -1,13 +0,0 @@ -package smecalculus.bezmen.messaging; - -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -/** - * Model: edge slice - */ -@Data -public class SepulkaNewRequestEdge { - @NotNull - private String externalId; -} diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEg.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEg.java deleted file mode 100644 index 8c8b6802..00000000 --- a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewRequestEg.java +++ /dev/null @@ -1,19 +0,0 @@ -package smecalculus.bezmen.messaging; - -import java.util.UUID; - -public class SepulkaNewRequestEg { - public static class Pojos { - public static SepulkaNewRequestEdge sepulkaNewRequestEdge() { - var requestEdge = new SepulkaNewRequestEdge(); - requestEdge.setExternalId(UUID.randomUUID().toString()); - return requestEdge; - } - - public static SepulkaNewRequestEdge sepulkaNewRequestEdge(String id) { - var requestEdge = sepulkaNewRequestEdge(); - requestEdge.setExternalId(id); - return requestEdge; - } - } -} diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEdge.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEdge.java deleted file mode 100644 index 403c24a7..00000000 --- a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEdge.java +++ /dev/null @@ -1,13 +0,0 @@ -package smecalculus.bezmen.messaging; - -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -/** - * Model: edge slice - */ -@Data -public class SepulkaNewResponseEdge { - @NotNull - private String externalId; -} diff --git a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEg.java b/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEg.java deleted file mode 100644 index eca1a5c1..00000000 --- a/libs/abstraction-client/src/main/java/smecalculus/bezmen/messaging/SepulkaNewResponseEg.java +++ /dev/null @@ -1,19 +0,0 @@ -package smecalculus.bezmen.messaging; - -import java.util.UUID; - -public class SepulkaNewResponseEg { - public static class Pojos { - public static SepulkaNewResponseEdge sepulkaNewResponseEdge() { - var responseEdge = new SepulkaNewResponseEdge(); - responseEdge.setExternalId(UUID.randomUUID().toString()); - return responseEdge; - } - - public static SepulkaNewResponseEdge sepulkaNewResponseEdge(String externalId) { - var responseEdge = sepulkaNewResponseEdge(); - responseEdge.setExternalId(externalId); - return responseEdge; - } - } -} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSide.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSide.java new file mode 100644 index 00000000..7e311224 --- /dev/null +++ b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSide.java @@ -0,0 +1,19 @@ +package smecalculus.bezmen.core; + +import lombok.Builder; +import lombok.NonNull; + +public class ClientSide { + + @Builder + public record RegistrationRequest(@NonNull String externalId) {} + + @Builder + public record RegistrationResponse(@NonNull String externalId) {} + + @Builder + public record PreviewRequest(@NonNull String externalId) {} + + @Builder + public record PreviewResponse(@NonNull String externalId) {} +} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSideEg.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSideEg.java new file mode 100644 index 00000000..0432dbdf --- /dev/null +++ b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ClientSideEg.java @@ -0,0 +1,14 @@ +package smecalculus.bezmen.core; + +import java.util.UUID; +import smecalculus.bezmen.core.ClientSide.RegistrationResponse; + +public class ClientSideEg { + public static RegistrationResponse.Builder registrationResponse() { + return RegistrationResponse.builder().externalId(UUID.randomUUID().toString()); + } + + public static RegistrationResponse.Builder registrationResponse(String externalId) { + return registrationResponse().externalId(externalId); + } +} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/Sepulka.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/Sepulka.java deleted file mode 100644 index 4f4edd0e..00000000 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/Sepulka.java +++ /dev/null @@ -1,11 +0,0 @@ -package smecalculus.bezmen.core; - -import java.util.UUID; -import lombok.Builder; -import lombok.NonNull; - -/** - * Model: domain entity - */ -@Builder -public record Sepulka(@NonNull UUID internalId, @NonNull String externalId) {} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaEg.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaEg.java deleted file mode 100644 index 2460ff00..00000000 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaEg.java +++ /dev/null @@ -1,31 +0,0 @@ -package smecalculus.bezmen.core; - -import java.util.UUID; - -public class SepulkaEg { - public static class Pojos { - public static Sepulka sepulka() { - return Builders.sepulka().build(); - } - - public static Sepulka sepulka(UUID id) { - return Builders.sepulka(id).build(); - } - } - - public static class Builders { - public static Sepulka.Builder sepulka() { - return Sepulka.builder() - .internalId(UUID.randomUUID()) - .externalId(UUID.randomUUID().toString()); - } - - public static Sepulka.Builder sepulka(UUID internalId) { - return sepulka().internalId(internalId); - } - - public static Sepulka.Builder sepulka(String externalId) { - return sepulka().externalId(externalId); - } - } -} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequest.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequest.java deleted file mode 100644 index 1038d6aa..00000000 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package smecalculus.bezmen.core; - -import lombok.Builder; -import lombok.NonNull; - -/** - * Model: domain slice - */ -@Builder -public record SepulkaNewRequest(@NonNull String externalId) {} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequestEg.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequestEg.java deleted file mode 100644 index 7a466fda..00000000 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewRequestEg.java +++ /dev/null @@ -1,17 +0,0 @@ -package smecalculus.bezmen.core; - -import java.util.UUID; - -public class SepulkaNewRequestEg { - public static class Pojos { - public static SepulkaNewRequest sepulkaNewRequest() { - return Builders.sepulkaNewRequest().build(); - } - } - - public static class Builders { - public static SepulkaNewRequest.Builder sepulkaNewRequest() { - return SepulkaNewRequest.builder().externalId(UUID.randomUUID().toString()); - } - } -} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponse.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponse.java deleted file mode 100644 index eca72d5f..00000000 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package smecalculus.bezmen.core; - -import lombok.Builder; -import lombok.NonNull; - -/** - * Model: domain slice - */ -@Builder -public record SepulkaNewResponse(@NonNull String externalId) {} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponseEg.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponseEg.java deleted file mode 100644 index 78c332dc..00000000 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaNewResponseEg.java +++ /dev/null @@ -1,21 +0,0 @@ -package smecalculus.bezmen.core; - -import java.util.UUID; - -public class SepulkaNewResponseEg { - public static class Pojos { - public static SepulkaNewResponse sepulkaNewResponse() { - return Builders.sepulkaNewResponse().build(); - } - - public static SepulkaNewResponse sepulkaNewResponse(String externalId) { - return new SepulkaNewResponse(externalId); - } - } - - public static class Builders { - public static SepulkaNewResponse.Builder sepulkaNewResponse() { - return SepulkaNewResponse.builder().externalId(UUID.randomUUID().toString()); - } - } -} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java index d28e2c56..dea35e73 100644 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java +++ b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaService.java @@ -1,9 +1,13 @@ package smecalculus.bezmen.core; import java.util.List; +import smecalculus.bezmen.core.ClientSide.PreviewRequest; +import smecalculus.bezmen.core.ClientSide.PreviewResponse; +import smecalculus.bezmen.core.ClientSide.RegistrationRequest; +import smecalculus.bezmen.core.ClientSide.RegistrationResponse; public interface SepulkaService { - SepulkaNewResponse register(SepulkaNewRequest request); + RegistrationResponse register(RegistrationRequest request); - List getSepulkas(); + List view(PreviewRequest request); } diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaSliceMapper.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaSliceMapper.java index 970d9cd9..2b15f84f 100644 --- a/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaSliceMapper.java +++ b/libs/abstraction/src/main/java/smecalculus/bezmen/core/SepulkaSliceMapper.java @@ -1,10 +1,13 @@ package smecalculus.bezmen.core; import org.mapstruct.Mapper; +import smecalculus.bezmen.core.ClientSide.RegistrationRequest; +import smecalculus.bezmen.core.ClientSide.RegistrationResponse; +import smecalculus.bezmen.core.ServerSide.AggregateState; @Mapper public interface SepulkaSliceMapper { - Sepulka.Builder toEntity(SepulkaNewRequest request); + AggregateState.Builder toServer(RegistrationRequest request); - SepulkaNewResponse toSlice(Sepulka sepulka); + RegistrationResponse.Builder toClient(AggregateState state); } diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSide.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSide.java new file mode 100644 index 00000000..a494f7e6 --- /dev/null +++ b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSide.java @@ -0,0 +1,25 @@ +package smecalculus.bezmen.core; + +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; +import lombok.NonNull; + +public class ServerSide { + @Builder + public record ExistenceState(@NonNull UUID internalId) {} + + @Builder + public record PreviewState(@NonNull String externalId, @NonNull LocalDateTime createdAt) {} + + @Builder + public record TouchState(@NonNull Integer revision, @NonNull LocalDateTime updatedAt) {} + + @Builder + public record AggregateState( + @NonNull UUID internalId, + @NonNull String externalId, + @NonNull Integer revision, + @NonNull LocalDateTime createdAt, + @NonNull LocalDateTime updatedAt) {} +} diff --git a/libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSideEg.java b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSideEg.java new file mode 100644 index 00000000..94a874cb --- /dev/null +++ b/libs/abstraction/src/main/java/smecalculus/bezmen/core/ServerSideEg.java @@ -0,0 +1,33 @@ +package smecalculus.bezmen.core; + +import static java.time.temporal.ChronoUnit.MICROS; + +import java.time.LocalDateTime; +import java.util.UUID; +import smecalculus.bezmen.core.ServerSide.AggregateState; +import smecalculus.bezmen.core.ServerSide.ExistenceState; +import smecalculus.bezmen.core.ServerSide.PreviewState; +import smecalculus.bezmen.core.ServerSide.TouchState; + +public class ServerSideEg { + public static AggregateState.Builder aggregateState() { + return AggregateState.builder() + .internalId(UUID.randomUUID()) + .externalId(UUID.randomUUID().toString()) + .revision(0) + .createdAt(LocalDateTime.now().truncatedTo(MICROS)) + .updatedAt(LocalDateTime.now().truncatedTo(MICROS)); + } + + public static ExistenceState.Builder creationState() { + return ExistenceState.builder().internalId(UUID.randomUUID()); + } + + public static PreviewState.Builder previewState(AggregateState state) { + return PreviewState.builder().externalId(state.externalId()).createdAt(state.createdAt()); + } + + public static TouchState.Builder touchState(AggregateState state) { + return TouchState.builder().revision(state.revision()).updatedAt(state.updatedAt()); + } +} diff --git a/libs/essentials/src/main/java/smecalculus/bezmen/validation/ValidationPropsMapper.java b/libs/essentials/src/main/java/smecalculus/bezmen/validation/ValidationPropsMapper.java index 24735a74..57349334 100644 --- a/libs/essentials/src/main/java/smecalculus/bezmen/validation/ValidationPropsMapper.java +++ b/libs/essentials/src/main/java/smecalculus/bezmen/validation/ValidationPropsMapper.java @@ -5,9 +5,10 @@ import smecalculus.bezmen.configuration.ValidationMode; import smecalculus.bezmen.configuration.ValidationProps; import smecalculus.bezmen.configuration.ValidationPropsEdge; +import smecalculus.bezmen.mapping.EdgeMapper; @Mapper -public interface ValidationPropsMapper { +public interface ValidationPropsMapper extends EdgeMapper { @Mapping(source = "mode", target = "validationMode") ValidationProps toDomain(ValidationPropsEdge propsEdge); diff --git a/libs/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java b/libs/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java index c8a20c01..d301f321 100644 --- a/libs/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java +++ b/libs/messaging-client/src/main/java/smecalculus/bezmen/messaging/BezmenClientJavaHttp.java @@ -10,6 +10,8 @@ import java.net.http.HttpResponse.BodyHandlers; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationRequest; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationResponse; @RequiredArgsConstructor public class BezmenClientJavaHttp implements BezmenClient { @@ -21,7 +23,7 @@ public class BezmenClientJavaHttp implements BezmenClient { private HttpClient client; @Override - public SepulkaNewResponseEdge register(SepulkaNewRequestEdge request) { + public RegistrationResponse register(RegistrationRequest request) { try { var requestJson = mapper.writeValueAsString(request); var httpRequest = HttpRequest.newBuilder() @@ -31,7 +33,7 @@ public SepulkaNewResponseEdge register(SepulkaNewRequestEdge request) { .header("Accept", "application/json") .build(); var httpResponse = client.send(httpRequest, BodyHandlers.ofString()); - return mapper.readValue(httpResponse.body(), SepulkaNewResponseEdge.class); + return mapper.readValue(httpResponse.body(), EdgeSide.RegistrationResponse.class); } catch (JsonProcessingException e) { throw new RuntimeException(e); } catch (IOException | InterruptedException e) { diff --git a/libs/messaging/src/main/java/smecalculus/bezmen/configuration/MessagingPropsMapper.java b/libs/messaging/src/main/java/smecalculus/bezmen/configuration/MessagingPropsMapper.java index 83e1aecd..82f625a2 100644 --- a/libs/messaging/src/main/java/smecalculus/bezmen/configuration/MessagingPropsMapper.java +++ b/libs/messaging/src/main/java/smecalculus/bezmen/configuration/MessagingPropsMapper.java @@ -2,9 +2,10 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import smecalculus.bezmen.mapping.EdgeMapper; @Mapper -public interface MessagingPropsMapper { +public interface MessagingPropsMapper extends EdgeMapper { @Mapping(source = "protocol", target = "protocolProps") @Mapping(source = "mapping", target = "mappingProps") diff --git a/libs/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java b/libs/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java index e8c08337..4b8cddf0 100644 --- a/libs/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java +++ b/libs/messaging/src/main/java/smecalculus/bezmen/messaging/SepulkaMessageMapper.java @@ -1,12 +1,12 @@ package smecalculus.bezmen.messaging; import org.mapstruct.Mapper; -import smecalculus.bezmen.core.SepulkaNewRequest; -import smecalculus.bezmen.core.SepulkaNewResponse; +import smecalculus.bezmen.core.ClientSide; +import smecalculus.bezmen.mapping.EdgeMapper; @Mapper -public interface SepulkaMessageMapper { - SepulkaNewRequest toDomain(SepulkaNewRequestEdge requestEdge); +public interface SepulkaMessageMapper extends EdgeMapper { + ClientSide.RegistrationRequest toDomain(EdgeSide.RegistrationRequest request); - SepulkaNewResponseEdge toEdge(SepulkaNewResponse response); + EdgeSide.RegistrationResponse toEdge(ClientSide.RegistrationResponse response); } diff --git a/libs/pom.xml b/libs/pom.xml index 1f9d536a..e6905ca8 100644 --- a/libs/pom.xml +++ b/libs/pom.xml @@ -342,13 +342,13 @@ org.apache.maven.plugins - maven-jar-plugin - 3.3.0 + maven-resources-plugin + 3.3.1 org.apache.maven.plugins - maven-resources-plugin - 3.3.1 + maven-jar-plugin + 3.3.0 org.apache.maven.plugins diff --git a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StateMappingPropsEg.java b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StateMappingPropsEg.java index cedc35dc..6d1b712c 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StateMappingPropsEg.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StateMappingPropsEg.java @@ -15,5 +15,9 @@ public static class Builders { public static StateMappingProps.Builder stateMappingProps() { return StateMappingProps.builder().mappingMode(SPRING_DATA); } + + public static StateMappingProps.Builder stateMappingProps(StateMappingMode mode) { + return stateMappingProps().mappingMode(mode); + } } } diff --git a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsEg.java b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsEg.java index 07267645..cd48ed64 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsEg.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsEg.java @@ -22,4 +22,10 @@ public static StorageProps.Builder storageProps() { .mappingProps(stateMappingProps().build()); } } + + public static StorageProps.Builder storageProps(StateMappingMode mappingMode, StorageProtocolMode protocolMode) { + return Builders.storageProps() + .protocolProps(storageProtocolProps(protocolMode).build()) + .mappingProps(stateMappingProps(mappingMode).build()); + } } diff --git a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsMapper.java b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsMapper.java index 20f92e46..e56d61ac 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsMapper.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StoragePropsMapper.java @@ -2,9 +2,10 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import smecalculus.bezmen.mapping.EdgeMapper; @Mapper -public interface StoragePropsMapper { +public interface StoragePropsMapper extends EdgeMapper { @Mapping(source = "protocol", target = "protocolProps") @Mapping(source = "mapping", target = "mappingProps") diff --git a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StorageProtocolPropsEg.java b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StorageProtocolPropsEg.java index 2154a710..43aeaf79 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/configuration/StorageProtocolPropsEg.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/configuration/StorageProtocolPropsEg.java @@ -24,5 +24,9 @@ public static StorageProtocolProps.Builder storageProtocolProps() { .password("bezmen") .build()); } + + public static StorageProtocolProps.Builder storageProtocolProps(StorageProtocolMode mode) { + return storageProtocolProps().protocolMode(mode); + } } } diff --git a/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingMyBatisBeans.java b/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingMyBatisBeans.java index 9bc58dc3..a0a50d21 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingMyBatisBeans.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingMyBatisBeans.java @@ -8,6 +8,7 @@ import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import smecalculus.bezmen.storage.mybatis.UuidTypeHandler; @ConditionalOnStateMappingMode(MY_BATIS) @MapperScan(basePackages = "smecalculus.bezmen.storage.mybatis") @@ -18,6 +19,7 @@ public class MappingMyBatisBeans { public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { var factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); + factoryBean.addTypeHandlers(new UuidTypeHandler()); return factoryBean.getObject(); } } diff --git a/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingSpringDataBeans.java b/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingSpringDataBeans.java index 9a2bad82..674f9e97 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingSpringDataBeans.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/construction/MappingSpringDataBeans.java @@ -2,14 +2,22 @@ import static smecalculus.bezmen.configuration.StateMappingMode.SPRING_DATA; +import java.util.Optional; import javax.sql.DataSource; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; +import org.springframework.data.jdbc.core.dialect.JdbcPostgresDialect; +import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration; import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories; +import org.springframework.data.relational.RelationalManagedTypes; import org.springframework.data.relational.core.dialect.Dialect; import org.springframework.data.relational.core.dialect.H2Dialect; -import org.springframework.data.relational.core.dialect.PostgresDialect; +import org.springframework.data.relational.core.mapping.NamingStrategy; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; @@ -20,6 +28,9 @@ @Configuration(proxyBeanMethods = false) public class MappingSpringDataBeans extends AbstractJdbcConfiguration { + @Autowired + private StorageProps storageProps; + @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { return new NamedParameterJdbcTemplate(dataSource); @@ -31,11 +42,22 @@ public PlatformTransactionManager transactionManager(DataSource dataSource) { } @Bean - public Dialect dialect(StorageProps storageProps) { - var storageProtocolProps = storageProps.protocolProps(); - return switch (storageProtocolProps.protocolMode()) { + @Override + public @NonNull Dialect jdbcDialect(@NonNull NamedParameterJdbcOperations operations) { + return switch (storageProps.protocolProps().protocolMode()) { case H2 -> H2Dialect.INSTANCE; - case POSTGRES -> PostgresDialect.INSTANCE; + case POSTGRES -> JdbcPostgresDialect.INSTANCE; }; } + + @Bean + @Override + public @NonNull JdbcMappingContext jdbcMappingContext( + @NonNull Optional namingStrategy, + @NonNull JdbcCustomConversions customConversions, + @NonNull RelationalManagedTypes jdbcManagedTypes) { + var mappingContext = super.jdbcMappingContext(namingStrategy, customConversions, jdbcManagedTypes); + mappingContext.setForceQuote(false); + return mappingContext; + } } diff --git a/libs/storage/src/main/java/smecalculus/bezmen/construction/StorageBeans.java b/libs/storage/src/main/java/smecalculus/bezmen/construction/StorageBeans.java index 78de9f9a..0f6cdb5a 100644 --- a/libs/storage/src/main/java/smecalculus/bezmen/construction/StorageBeans.java +++ b/libs/storage/src/main/java/smecalculus/bezmen/construction/StorageBeans.java @@ -9,17 +9,17 @@ import smecalculus.bezmen.configuration.PostgresProps; import smecalculus.bezmen.configuration.StorageProps; -@Configuration(proxyBeanMethods = false) @Import({StorageConfigBeans.class, MappingMyBatisBeans.class, MappingSpringDataBeans.class}) +@Configuration(proxyBeanMethods = false) public class StorageBeans { @Bean public DataSource dataSource(StorageProps storageProps) { var dataSource = new DriverManagerDataSource(); - var storageProtocolProps = storageProps.protocolProps(); - switch (storageProtocolProps.protocolMode()) { - case H2 -> configure(dataSource, storageProtocolProps.h2Props()); - case POSTGRES -> configure(dataSource, storageProtocolProps.postgresProps()); + var protocolProps = storageProps.protocolProps(); + switch (protocolProps.protocolMode()) { + case H2 -> configure(dataSource, protocolProps.h2Props()); + case POSTGRES -> configure(dataSource, protocolProps.postgresProps()); } return dataSource; } diff --git a/libs/storage/src/main/java/smecalculus/bezmen/storage/mybatis/UuidTypeHandler.java b/libs/storage/src/main/java/smecalculus/bezmen/storage/mybatis/UuidTypeHandler.java new file mode 100644 index 00000000..5ca0998c --- /dev/null +++ b/libs/storage/src/main/java/smecalculus/bezmen/storage/mybatis/UuidTypeHandler.java @@ -0,0 +1,42 @@ +package smecalculus.bezmen.storage.mybatis; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.UUID; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; + +/** + * If the issue ever gets resolved + * Then we can use String type with overridden JdbcType in the edge model {@link smecalculus.bezmen.storage.EdgeSide.AggregateState#internalId}. + * So that type handler can be removed completely. + */ +public class UuidTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) + throws SQLException { + ps.setObject(i, parameter.toString(), Types.OTHER); + } + + @Override + public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException { + var uuidString = rs.getString(columnName); + return uuidString == null ? null : UUID.fromString(uuidString); + } + + @Override + public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + var uuidString = rs.getString(columnIndex); + return uuidString == null ? null : UUID.fromString(uuidString); + } + + @Override + public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + var uuidString = cs.getString(columnIndex); + return uuidString == null ? null : UUID.fromString(uuidString); + } +} diff --git a/libs/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java b/libs/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java index 3ab08015..55e5d55c 100644 --- a/libs/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java +++ b/libs/testing/src/main/java/smecalculus/bezmen/messaging/SepulkaClientSpringWebTest.java @@ -4,6 +4,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.test.web.reactive.server.WebTestClient; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationRequest; +import smecalculus.bezmen.messaging.EdgeSide.RegistrationResponse; @RequiredArgsConstructor public class SepulkaClientSpringWebTest implements SepulkaClient { @@ -12,14 +14,14 @@ public class SepulkaClientSpringWebTest implements SepulkaClient { private WebTestClient client; @Override - public SepulkaNewResponseEdge register(SepulkaNewRequestEdge request) { + public RegistrationResponse register(RegistrationRequest request) { return client.post() .uri("/sepulkas") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .bodyValue(request) .exchange() - .expectBody(SepulkaNewResponseEdge.class) + .expectBody(RegistrationResponse.class) .returnResult() .getResponseBody(); } diff --git a/schemas/h2/sepulkarium/create.sql b/schemas/h2/sepulkarium/create.sql index 033a7f97..4a473bfb 100644 --- a/schemas/h2/sepulkarium/create.sql +++ b/schemas/h2/sepulkarium/create.sql @@ -1,5 +1,7 @@ CREATE TABLE sepulkas ( - internal_id CHARACTER VARYING, - external_id CHARACTER VARYING, - version INTEGER + internal_id UUID UNIQUE, + external_id CHARACTER VARYING (64) UNIQUE, + revision INTEGER, + created_at TIMESTAMP (6), + updated_at TIMESTAMP (6) ); diff --git a/schemas/postgres/sepulkarium/owner/sepulkas.sql b/schemas/postgres/sepulkarium/owner/sepulkas.sql index f304b607..7293d961 100644 --- a/schemas/postgres/sepulkarium/owner/sepulkas.sql +++ b/schemas/postgres/sepulkarium/owner/sepulkas.sql @@ -1,5 +1,7 @@ CREATE TABLE sepulkas ( - internal_id text, - external_id text, - version integer + internal_id uuid UNIQUE, + external_id character varying (64) UNIQUE, + revision integer, + created_at TIMESTAMP (6), + updated_at TIMESTAMP (6) ); diff --git a/tests/e2e/pom.xml b/tests/e2e/pom.xml index 633e9703..c8416ab5 100644 --- a/tests/e2e/pom.xml +++ b/tests/e2e/pom.xml @@ -50,6 +50,7 @@ org.apache.maven.plugins maven-surefire-plugin + ${project.parent.basedir}/props/${props}.properties smecalculus.bezmen.${suite.name} diff --git a/tests/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java b/tests/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java index 976de482..ea28af5e 100644 --- a/tests/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java +++ b/tests/e2e/src/test/java/smecalculus/bezmen/registration/SepulkaTest.java @@ -3,8 +3,6 @@ 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.SepulkaNewRequestEg.Pojos.sepulkaNewRequestEdge; -import static smecalculus.bezmen.messaging.SepulkaNewResponseEg.Pojos.sepulkaNewResponseEdge; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Tag; @@ -16,6 +14,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import smecalculus.bezmen.StandBeans; import smecalculus.bezmen.messaging.BezmenClient; +import smecalculus.bezmen.messaging.EdgeSideEg; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = StandBeans.class) @@ -33,9 +32,9 @@ void beforeAll() { @Tag("smoke") void shouldRegisterSepulka() { // given - var request = sepulkaNewRequestEdge(); + var request = EdgeSideEg.registrationRequest(); // and - var expectedResponse = sepulkaNewResponseEdge(request.getExternalId()); + var expectedResponse = EdgeSideEg.registrationResponse(request.getExternalId()); // when var actualResponse = bezmenClient.register(request); // then diff --git a/tests/pom.xml b/tests/pom.xml index 3dcdfd38..1d1098db 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -47,10 +47,6 @@ com.diffplug.spotless spotless-maven-plugin - - org.apache.maven.plugins - maven-compiler-plugin - org.apache.maven.plugins maven-surefire-plugin @@ -121,9 +117,6 @@ org.apache.maven.plugins maven-surefire-plugin 3.1.2 - - ${project.parent.basedir}/props/${props}.properties - org.apache.maven.plugins diff --git a/tools/pom.xml b/tools/pom.xml index d32aecc2..0c8dcf58 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -73,7 +73,7 @@ - +