diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/EdcChatApplication.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/EdcChatApplication.java new file mode 100644 index 0000000..ac41e3c --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/EdcChatApplication.java @@ -0,0 +1,18 @@ +package com.smartsense.chat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@SpringBootApplication +@ConfigurationPropertiesScan +@EnableFeignClients +public class EdcChatApplication { + + public static void main(String[] args) { + SpringApplication.run(EdcChatApplication.class, args); + } + +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/ServletInitializer.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/ServletInitializer.java new file mode 100644 index 0000000..1258f4f --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/ServletInitializer.java @@ -0,0 +1,13 @@ +package com.smartsense.chat; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(EdcChatApplication.class); + } + +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/dao/entity/BusinessPartner.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/dao/entity/BusinessPartner.java new file mode 100644 index 0000000..a1a5d09 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/dao/entity/BusinessPartner.java @@ -0,0 +1,51 @@ +package com.smartsense.chat.dao.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.*; +import lombok.*; + +import java.util.Date; +import java.util.UUID; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "raw_data_master") +public class BusinessPartner { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "id", nullable = false, updatable = false, insertable = false) + private final UUID id = UUID.randomUUID(); + + @Column(name = "name") + private String name; + + @Column(name = "bpn") + private String bpn; + + @Column(name = "edc_url") + private String edcUrl; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "created_at", updatable = false, nullable = false) + private Date createdAt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "updated_at") + @JsonIgnore + private Date updatedAt; + + @PrePersist + void createdAt() { + this.createdAt = new Date(); + } + + @PreUpdate + void updatedAt() { + this.updatedAt = new Date(); + } +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/dao/repository/BusinessPartnerRepository.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/dao/repository/BusinessPartnerRepository.java new file mode 100644 index 0000000..fed520e --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/dao/repository/BusinessPartnerRepository.java @@ -0,0 +1,11 @@ +package com.smartsense.chat.dao.repository; + +import com.smartsense.chat.dao.entity.BusinessPartner; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface BusinessPartnerRepository extends JpaRepository { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/EDCService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/EDCService.java new file mode 100644 index 0000000..fd24cc6 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/EDCService.java @@ -0,0 +1,37 @@ +package com.smartsense.chat.edc; + +import com.smartsense.chat.edc.operation.PublicUrlHandlerService; +import com.smartsense.chat.edc.operation.TransferProcessService; +import com.smartsense.chat.utils.request.ChatMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.net.URI; + +@Service +@RequiredArgsConstructor +@Slf4j +public class EDCService { + + + private final TransferProcessService transferProcessService; + private final PublicUrlHandlerService publicUrlHandlerService; + + public void initProcess(URI edcUri, ChatMessage chatMessage) { + // TODO query catalog + //TODO start negotiation + //TODO get agreement + + + String agreementId = null; + + // Initiate the transfer process + String transferProcessId = transferProcessService.initiateTransfer(edcUri, agreementId); + + // sent the message to public url + publicUrlHandlerService.getAuthCodeAndPublicUrl(edcUri, transferProcessId, chatMessage); + } + + +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/client/EDCConnectorClient.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/client/EDCConnectorClient.java new file mode 100644 index 0000000..b34f5af --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/client/EDCConnectorClient.java @@ -0,0 +1,44 @@ +package com.smartsense.chat.edc.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.*; + +import java.net.URI; +import java.util.List; +import java.util.Map; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@FeignClient(name = "edc", url = "http://localhost:8182") +public interface EDCConnectorClient { + + @PostMapping(value = "/management/v2/catalog/request", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + Map queryCatalog(URI baseUri, + @RequestBody Map request, + @RequestHeader("X-Api-Key") String auth); + + @PostMapping(value = "/management/v2/edrs", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + Map initNegotiation(URI baseUri, + @RequestBody Map request, + @RequestHeader("X-Api-Key") String auth); + + @GetMapping(value = "/management/v2/contractnegotiations/{negotiationId}", produces = APPLICATION_JSON_VALUE) + Map getAgreement(URI baseUri, + @PathVariable("negotiationId") String negotiationId, + @RequestHeader("X-Api-Key") String auth); + + + @PostMapping(value = "/management/v2/edrs/request", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + List> initTransferProcess(URI baseUri, + @RequestBody Map request, + @RequestHeader("X-Api-Key") String auth); + + @GetMapping(value = "management/v2/edrs/{transferProcessId}/dataaddress", produces = APPLICATION_JSON_VALUE) + Map getAuthCodeAndPublicUrl(URI baseUri, + @PathVariable("transferProcessId") String transferProcessId, + @RequestHeader("X-Api-Key") String auth); + + @PostMapping(consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + Map sendMessage(URI baseUri, @RequestBody String message, @RequestHeader("Authorization") String authorization); + +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/AgreementFetcherService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/AgreementFetcherService.java new file mode 100644 index 0000000..d1ba8c5 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/AgreementFetcherService.java @@ -0,0 +1,4 @@ +package com.smartsense.chat.edc.operation; + +public class AgreementFetcherService { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/ContractNegotiationService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/ContractNegotiationService.java new file mode 100644 index 0000000..6737332 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/ContractNegotiationService.java @@ -0,0 +1,4 @@ +package com.smartsense.chat.edc.operation; + +public class ContractNegotiationService { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/PublicUrlHandlerService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/PublicUrlHandlerService.java new file mode 100644 index 0000000..c120ebb --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/PublicUrlHandlerService.java @@ -0,0 +1,50 @@ +package com.smartsense.chat.edc.operation; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.smartsense.chat.edc.client.EDCConnectorClient; +import com.smartsense.chat.utils.request.ChatMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.net.URI; +import java.util.Map; + +@Service +@RequiredArgsConstructor +@Slf4j +public class PublicUrlHandlerService { + private final EDCConnectorClient edc; + private final ObjectMapper mapper; + @Value("${edc.auth.code:password}") + private String authCode; + + public void getAuthCodeAndPublicUrl(URI edcUri, String transferProcessId, ChatMessage message) { + try { + log.info("Initiate to get auth code based on transfer process id " + transferProcessId); + Map response = edc.getAuthCodeAndPublicUrl(edcUri, transferProcessId, authCode); + log.info("Auth code and public url response -> {}", response); + + // Retrieve public path and authorization code + String publicPath = response.get("tx-auth:refreshEndpoint").toString(); + String authorization = response.get("authorization").toString(); + + // Call the public path with authorization code + callPublicUri(publicPath, mapper.writeValueAsString(message), authorization); + + log.info("Initiate to get auth code based on transfer process id {} is done.", transferProcessId); + } catch (Exception ex) { + log.error("Error occurred in get auth code based on transfer process id {} ", transferProcessId, ex); + } + } + + private void callPublicUri(String publicPath, String message, String authorization) { + try { + Map publicUriResponse = edc.sendMessage(URI.create(publicPath), message, authorization); + log.info("Received public uri response -> {}", publicUriResponse); + } catch (Exception ex) { + log.error("Error occurred while calling public uri {} and auth code {} ", publicPath, authorization, ex); + } + } +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/QueryCatalogService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/QueryCatalogService.java new file mode 100644 index 0000000..b7d4b2e --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/QueryCatalogService.java @@ -0,0 +1,4 @@ +package com.smartsense.chat.edc.operation; + +public class QueryCatalogService { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/TransferProcessService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/TransferProcessService.java new file mode 100644 index 0000000..9821a88 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/operation/TransferProcessService.java @@ -0,0 +1,57 @@ +package com.smartsense.chat.edc.operation; + +import com.smartsense.chat.edc.client.EDCConnectorClient; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +@Slf4j +public class TransferProcessService { + + private final EDCConnectorClient edc; + @Value("${edc.auth.code:password}") + private String authCode; + + public String initiateTransfer(URI edcUri, String agreementId) { + try { + log.info("Initiate transfer process for agreement Id {}", agreementId); + + // prepare transfer request + Map transferRequest = prepareTransferRequest(agreementId); + // initiate the transfer process + List> transferResponse = edc.initTransferProcess(edcUri, transferRequest, authCode); + log.info("Received transfer response -> {}", transferResponse); + + // get the transfer process id from response + String transferProcessId = transferResponse.get(0).get("transferProcessId").toString(); + log.info("Transfer process id: {}", transferProcessId); + + log.info("Transfer process is complete successfully for agreement Id {}", agreementId); + return transferProcessId; + } catch (Exception ex) { + log.error("Error occurred in transfer process for agreement Id {}", agreementId, ex); + return null; + } + } + + private Map prepareTransferRequest(String agreementId) { + Map transferRequest = new HashMap<>(); + transferRequest.put("@context", Map.of("@vocab", "https://w3id.org/edc/v0.0.1/ns/")); + transferRequest.put("@type", "QuerySpec"); + transferRequest.put("offset", 0); + transferRequest.put("limit", 1); + transferRequest.put("filterExpression", List.of(Map.of("operandLeft", "agreementId", + "operator", "=", + "operandRight", agreementId))); + log.info("Transfer request looks like: {}", transferRequest); + return transferRequest; + } +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/settings/EDCConfigurations.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/settings/EDCConfigurations.java new file mode 100644 index 0000000..6eec751 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/edc/settings/EDCConfigurations.java @@ -0,0 +1,8 @@ +package com.smartsense.chat.edc.settings; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("chat.edc") +public record EDCConfigurations(String authCode, + String assetId) { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/service/BusinessPartnerService.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/service/BusinessPartnerService.java new file mode 100644 index 0000000..7daaf1d --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/service/BusinessPartnerService.java @@ -0,0 +1,29 @@ +package com.smartsense.chat.service; + +import com.smartsense.chat.dao.entity.BusinessPartner; +import com.smartsense.chat.dao.repository.BusinessPartnerRepository; +import com.smartsense.chat.utils.request.BusinessPartnerRequest; +import com.smartsense.chat.web.BusinessPartnerResource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class BusinessPartnerService { + + private final BusinessPartnerRepository businessPartnerRepository; + + + public BusinessPartnerResource createBusinessPartner(BusinessPartnerRequest request) { + log.info("Creating BusinessPartner. name: {}", request.name()); + BusinessPartner businessPartner = BusinessPartner.builder() + .name(request.name()) + .edcUrl(request.edcUrl()) + .bpn(request.bpn()) + .build(); + businessPartnerRepository.save(businessPartner); + return null; + } +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/exception/BadDataException.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/exception/BadDataException.java new file mode 100644 index 0000000..85baa1b --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/exception/BadDataException.java @@ -0,0 +1,25 @@ +package com.smartsense.chat.utils.exception; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serial; + +@NoArgsConstructor +@Getter +public class BadDataException extends RuntimeException { + @Serial + private static final long serialVersionUID = 5732404099105408974L; + + private String code; + private String message; + + public BadDataException(String message) { + this.message = message; + } + + public BadDataException(String message, String code) { + this.message = message; + this.code = code; + } +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/request/BusinessPartnerRequest.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/request/BusinessPartnerRequest.java new file mode 100644 index 0000000..603485d --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/request/BusinessPartnerRequest.java @@ -0,0 +1,6 @@ +package com.smartsense.chat.utils.request; + +public record BusinessPartnerRequest(String name, + String bpn, + String edcUrl) { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/request/ChatMessage.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/request/ChatMessage.java new file mode 100644 index 0000000..5667066 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/request/ChatMessage.java @@ -0,0 +1,7 @@ +package com.smartsense.chat.utils.request; + +public record ChatMessage(String senderBpn, + String receiverBpn, + String message, + String messageId) { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/response/BusinessPartnerResponse.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/response/BusinessPartnerResponse.java new file mode 100644 index 0000000..970bb43 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/response/BusinessPartnerResponse.java @@ -0,0 +1,9 @@ +package com.smartsense.chat.utils.response; + +import java.util.UUID; + +public record BusinessPartnerResponse(UUID id, + String name, + String bpn, + String edcUrl) { +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/validate/Validate.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/validate/Validate.java new file mode 100644 index 0000000..351af7a --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/utils/validate/Validate.java @@ -0,0 +1,133 @@ +package com.smartsense.chat.utils.validate; + + +import com.smartsense.chat.utils.exception.BadDataException; + +import java.util.Objects; +import java.util.function.Function; + + +public class Validate { + private T value; + private boolean match = false; + + private Validate() { + } + + private Validate(T value) { + this.value = value; + } + + public static Validate value(V value) { + return new Validate<>(value); + } + + public static Validate isTrue(boolean condition) { + Validate validate = new Validate<>(); + if (condition) { + validate.match = true; + } + return validate; + } + + /** + * Throws if {@code condition} is false + * + * @param condition the condition + * @param + * @return + */ + public static Validate isFalse(boolean condition) { + Validate validate = new Validate<>(); + if (!condition) { + validate.match = true; + } + return validate; + } + + public static Validate isNull(T value) { + return new Validate<>(value).isNull(); + } + + public static Validate isNotNull(T value) { + return new Validate<>(value).isNotNull(); + } + + public Validate inLength(int min, int max) { + if (Objects.isNull(value)) { + return this; + } + if (match || value.toString().length() < min && value.toString().length() > max) { + match = true; + } + return this; + } + + public Validate isNotEmpty() { + if (match || Objects.isNull(value) || String.valueOf(value).trim().isEmpty()) { + match = true; + } + return this; + } + + public Validate isNull() { + if (match || Objects.isNull(value)) { + match = true; + } + return this; + } + + public Validate isNotNull() { + if (match || !Objects.isNull(value)) { + match = true; + } + return this; + } + + public Validate check(Function checkFunction) { + if (match || checkFunction.apply(value)) { + match = true; + } + return this; + } + + public Validate checkNot(Function checkFunction) { + if (match || !checkFunction.apply(value)) { + match = true; + } + return this; + } + + /** + * Throw passed exception if expression is match + * + * @param e exception to throw + */ + public T launch(RuntimeException e) { + if (match) { + throw e; + } + return value; + } + + /** + * Throw {@code BadDataException} if expression is match with passed message + * + * @param message exception message + */ + public T launch(String message) { + if (match) { + throw new BadDataException(message); + } + return value; + } + + /** + * Calculate all of the conditions are true or not + * + * @return true if any of condition are true + */ + public boolean calculate() { + return match; + } +} diff --git a/edc-chat-app-backend/src/main/java/com/smartsense/chat/web/BusinessPartnerResource.java b/edc-chat-app-backend/src/main/java/com/smartsense/chat/web/BusinessPartnerResource.java new file mode 100644 index 0000000..a8ef074 --- /dev/null +++ b/edc-chat-app-backend/src/main/java/com/smartsense/chat/web/BusinessPartnerResource.java @@ -0,0 +1,27 @@ +package com.smartsense.chat.web; + +import com.smartsense.chat.service.BusinessPartnerService; +import com.smartsense.chat.utils.request.BusinessPartnerRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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 static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/api/partner") +public class BusinessPartnerResource { + + private final BusinessPartnerService businessPartnerService; + + + @PostMapping(value = "/create", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + public BusinessPartnerResource createBusinessPartner(@RequestBody BusinessPartnerRequest request) { + return businessPartnerService.createBusinessPartner(request); + } +} diff --git a/edc-chat-app-backend/src/main/resources/application.yaml b/edc-chat-app-backend/src/main/resources/application.yaml new file mode 100644 index 0000000..d6bf036 --- /dev/null +++ b/edc-chat-app-backend/src/main/resources/application.yaml @@ -0,0 +1,26 @@ +chat: + edc: + authCode: password + assetId: edc-chat-app + + +spring: + application: + name: EDC based chat application + threads: + virtual: + enabled: true + jpa: + hibernate: + ddl-auto: none + properties: + hibernate.default_schema: public + show-sql: true + datasource: + url: jdbc:postgresql://localhost:5432/chat_app + username: postgres + password: 123456 + driver-class-name: org.postgresql.Driver + liquibase: + change-log: classpath:db/changelog/changelog-master.yaml + diff --git a/edc-chat-app-backend/src/main/resources/db/changelog/changelog-master.yaml b/edc-chat-app-backend/src/main/resources/db/changelog/changelog-master.yaml new file mode 100644 index 0000000..a5601d6 --- /dev/null +++ b/edc-chat-app-backend/src/main/resources/db/changelog/changelog-master.yaml @@ -0,0 +1,3 @@ +databaseChangeLog: + - include: + file: db/changelog/changes/1-initial-table-structure.sql diff --git a/edc-chat-app-backend/src/main/resources/db/changelog/changes/1-initial-table-structure.sql b/edc-chat-app-backend/src/main/resources/db/changelog/changes/1-initial-table-structure.sql new file mode 100644 index 0000000..96d887d --- /dev/null +++ b/edc-chat-app-backend/src/main/resources/db/changelog/changes/1-initial-table-structure.sql @@ -0,0 +1,13 @@ +--liquibase formatted sql + +--changeset Bhautik:1 +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE TABLE business_partner +( + id UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(), + name varchar(100) NOT NULL, + bpn varchar(50) NOT NULL, + edc_url varchar(50) NOT NULL, + created_at timestamp(6) NULL DEFAULT NOW(), + updated_at timestamp(6) NULL DEFAULT NOW() +); diff --git a/edc-chat-app-backend/src/test/java/com/smartsense/chat/EdcChatApplicationTests.java b/edc-chat-app-backend/src/test/java/com/smartsense/chat/EdcChatApplicationTests.java new file mode 100644 index 0000000..575b534 --- /dev/null +++ b/edc-chat-app-backend/src/test/java/com/smartsense/chat/EdcChatApplicationTests.java @@ -0,0 +1,15 @@ +package com.smartsense.chat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +class EdcChatApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/edc-chat-app-backend/src/test/java/com/smartsense/chat/TestEdcChatApplication.java b/edc-chat-app-backend/src/test/java/com/smartsense/chat/TestEdcChatApplication.java new file mode 100644 index 0000000..756f4c3 --- /dev/null +++ b/edc-chat-app-backend/src/test/java/com/smartsense/chat/TestEdcChatApplication.java @@ -0,0 +1,11 @@ +package com.smartsense.chat; + +import org.springframework.boot.SpringApplication; + +public class TestEdcChatApplication { + + public static void main(String[] args) { + SpringApplication.from(EdcChatApplication::main).with(TestcontainersConfiguration.class).run(args); + } + +} diff --git a/edc-chat-app-backend/src/test/java/com/smartsense/chat/TestcontainersConfiguration.java b/edc-chat-app-backend/src/test/java/com/smartsense/chat/TestcontainersConfiguration.java new file mode 100644 index 0000000..9b574f9 --- /dev/null +++ b/edc-chat-app-backend/src/test/java/com/smartsense/chat/TestcontainersConfiguration.java @@ -0,0 +1,18 @@ +package com.smartsense.chat; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.utility.DockerImageName; + +@TestConfiguration(proxyBeanMethods = false) +class TestcontainersConfiguration { + + @Bean + @ServiceConnection + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + } + +}