From 374fa94e064defd968b07bfa67ecf7af5367f54e Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Wed, 25 Mar 2026 14:34:00 +0100 Subject: [PATCH 1/4] Add mocks for create/get component. --- .../openapi/api-project-component-v0.yaml | 6 +- .../ProjectComponentsController.java | 4 +- .../project/facade/ComponentsFacade.java | 23 +----- .../project/mock/ComponentMockService.java | 75 +++++++++++++++++++ .../project/facade/ComponentsServiceTest.java | 13 ++-- core/pom.xml | 6 ++ 6 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java diff --git a/api-project-component-v0/openapi/api-project-component-v0.yaml b/api-project-component-v0/openapi/api-project-component-v0.yaml index dcd3912..868e72e 100644 --- a/api-project-component-v0/openapi/api-project-component-v0.yaml +++ b/api-project-component-v0/openapi/api-project-component-v0.yaml @@ -12,14 +12,14 @@ servers: default: localhost:8080 description: Development environment tags: - - name: ProjectComponents + - name: Project Components description: API for managing project components paths: /projects/{projectId}/components/: post: tags: - - projectComponents + - Project Components summary: Create a component in a project operationId: createProjectComponent description: Retrieves information about a specific component @@ -61,7 +61,7 @@ paths: /projects/{projectId}/components/{componentId}: get: tags: - - projectComponents + - Project Components summary: Get component information operationId: getProjectComponent description: Retrieves information about a specific component diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java index 9f50dee..9c6c4d7 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java @@ -3,18 +3,20 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.opendevstack.apiservice.project.api.ProjectComponentsApi; +import org.opendevstack.apiservice.project.facade.ComponentsFacade; import org.opendevstack.apiservice.project.mapper.ComponentResponseMapper; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.opendevstack.apiservice.project.model.CreateComponentResponse; -import org.opendevstack.apiservice.project.facade.ComponentsFacade; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @AllArgsConstructor @Slf4j +@RequestMapping("/api/pub/v0") public class ProjectComponentsController implements ProjectComponentsApi { private final ComponentsFacade componentsFacade; diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java index 012f21d..ed85fcd 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java @@ -2,7 +2,7 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.opendevstack.apiservice.externalservice.api.ExternalService; +import org.opendevstack.apiservice.project.mock.ComponentMockService; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.springframework.stereotype.Service; @@ -12,7 +12,7 @@ @Slf4j public class ComponentsFacade { - private final MarketplaceExternalServicePlaceholder marketplaceExternalService; + private final ComponentMockService marketplaceExternalService; public Component getProjectComponent(String projectId, String componentId) { return marketplaceExternalService.getProjectComponent(projectId, componentId); @@ -21,23 +21,4 @@ public Component getProjectComponent(String projectId, String componentId) { public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { return marketplaceExternalService.createProjectComponent(projectId, createComponentRequest); } - - @Service - class MarketplaceExternalServicePlaceholder implements ExternalService { - - @Override - public boolean isHealthy() { - return false; - } - - public Component getProjectComponent(String projectId, String componentId) { - log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); - return null; - } - - public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { - log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentRequest); - return null; - } - } } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java new file mode 100644 index 0000000..55ba231 --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java @@ -0,0 +1,75 @@ +package org.opendevstack.apiservice.project.mock; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.opendevstack.apiservice.externalservice.api.ExternalService; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Service +@AllArgsConstructor +@Slf4j +public class ComponentMockService implements ExternalService { + + @Override + public boolean isHealthy() { + return true; + } + + private Map mockComponentsCache = Collections.synchronizedMap(new HashMap<>()); + + public Component getProjectComponent(String projectId, String componentId) { + log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); + ComposedId composedId = new ComposedId(projectId, componentId); + return mockComponentsCache.get(composedId); + } + + public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { + log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentRequest); + Component mockComponent = new Component(); + mockComponent.setId(generateNextId()); + mockComponent.setName("Mock Component " + mockComponent.getId() + " for project " + projectId); + synchronized (mockComponentsCache) { + ComposedId composedId = new ComposedId(projectId, mockComponent.getId()); + mockComponentsCache.put(composedId, mockComponent); + } + return mockComponent; + } + + private String generateNextId() { + return "mock-component-id-" + (mockComponentsCache.size() + 1); + } + + class ComposedId { + private String projectId; + private String componentId; + + public ComposedId(String projectId, String componentId) { + this.projectId = projectId; + this.componentId = componentId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ComposedId that = (ComposedId) o; + + if (!projectId.equals(that.projectId)) return false; + return componentId.equals(that.componentId); + } + + @Override + public int hashCode() { + int result = projectId.hashCode(); + result = 31 * result + componentId.hashCode(); + return result; + } + } +} diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java index 31d2bcb..be94a6f 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.opendevstack.apiservice.project.mock.ComponentMockService; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; @@ -19,20 +20,20 @@ class ComponentsServiceTest { @Mock - private ComponentsFacade.MarketplaceExternalServicePlaceholder marketPlaceExternalServicePlaceholder; + private ComponentMockService marketPlaceExternalService; private ComponentsFacade componentsFacade; @BeforeEach void setup() { - componentsFacade = new ComponentsFacade(marketPlaceExternalServicePlaceholder); + componentsFacade = new ComponentsFacade(marketPlaceExternalService); } @Test void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { Component testComponent = buildTestComponent(); - when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) + when(marketPlaceExternalService.getProjectComponent(anyString(), eq("testId"))) .thenReturn(testComponent); Component retrievedComponent = componentsFacade.getProjectComponent("testId", "testId"); @@ -41,7 +42,7 @@ void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exc @Test void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Exception { - when(marketPlaceExternalServicePlaceholder.getProjectComponent(anyString(), eq("testId"))) + when(marketPlaceExternalService.getProjectComponent(anyString(), eq("testId"))) .thenReturn(null); Component retrievedComponent = componentsFacade.getProjectComponent("testId", "testId"); @@ -53,7 +54,7 @@ void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Component testComponent = buildTestComponent(); CreateComponentRequest testRequest = buildTestCreateComponentRequest(); - when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) + when(marketPlaceExternalService.createProjectComponent(anyString(), eq(testRequest))) .thenReturn(testComponent); Component retrievedComponent = componentsFacade.createProjectComponent("testId", testRequest); @@ -65,7 +66,7 @@ void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws void testCreateProjectComponent_whenFailure_thenReturnNull() throws Exception { CreateComponentRequest testRequest = buildTestCreateComponentRequest(); - when(marketPlaceExternalServicePlaceholder.createProjectComponent(anyString(), eq(testRequest))) + when(marketPlaceExternalService.createProjectComponent(anyString(), eq(testRequest))) .thenReturn(null); Component retrievedComponent = componentsFacade.createProjectComponent("testId", testRequest); diff --git a/core/pom.xml b/core/pom.xml index c3aa14b..e794fa2 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -121,6 +121,12 @@ ${project.version} + + org.opendevstack.apiservice + api-project-component-v0 + ${project.version} + + org.opendevstack.apiservice api-project-platform From 0e167d852027cf19f1a536131b5c9612a2673998 Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Tue, 31 Mar 2026 11:49:26 +0200 Subject: [PATCH 2/4] Add marketplace external service mock. --- api-project-component-v0/pom.xml | 7 + .../controller/ComponentsResponseFactory.java | 4 +- .../ProjectComponentsController.java | 4 +- .../project/facade/ComponentsFacade.java | 26 +++- .../project/mapper/MarketplaceMapper.java | 30 ++++ .../ProjectComponentsControllerTest.java | 2 +- ...iceTest.java => ComponentsFacadeTest.java} | 36 +++-- .../project/util/TestObjectsBuilder.java | 24 +++- core/pom.xml | 6 + external-service-marketplace/pom.xml | 129 ++++++++++++++++++ .../model/CreateComponentParameter.java | 17 +++ .../marketplace/model/ProjectComponent.java | 18 +++ .../service/MarketplaceService.java | 15 ++ .../impl/MarketplaceServiceMockImpl.java | 30 ++-- pom.xml | 1 + 15 files changed, 311 insertions(+), 38 deletions(-) create mode 100644 api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/MarketplaceMapper.java rename api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/{ComponentsServiceTest.java => ComponentsFacadeTest.java} (58%) create mode 100644 external-service-marketplace/pom.xml create mode 100644 external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/CreateComponentParameter.java create mode 100644 external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/ProjectComponent.java create mode 100644 external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/MarketplaceService.java rename api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java => external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java (61%) diff --git a/api-project-component-v0/pom.xml b/api-project-component-v0/pom.xml index a3f50df..845c6d5 100644 --- a/api-project-component-v0/pom.xml +++ b/api-project-component-v0/pom.xml @@ -44,6 +44,12 @@ ${project.version} + + org.opendevstack.apiservice + external-service-marketplace + ${project.version} + + io.jsonwebtoken jjwt-api @@ -89,6 +95,7 @@ spring-boot-starter-test test + org.springframework.security spring-security-core diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java index 7eb10ce..c3f876a 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ComponentsResponseFactory.java @@ -15,10 +15,10 @@ public static CreateComponentResponse error(String projectId) { return response; } - public static CreateComponentResponse entityCreated(String projectId, String componentName) { + public static CreateComponentResponse entityCreated(String projectId, String componentId) { CreateComponentResponse response = new CreateComponentResponse(); response.setErrorCode(HttpStatus.CREATED.value()); - response.setMessage(componentName + " component created successfully in project " + projectId); + response.setMessage(componentId + " component created successfully in project " + projectId); return response; } } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java index 9c6c4d7..f8b0ae8 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/controller/ProjectComponentsController.java @@ -27,11 +27,12 @@ public class ProjectComponentsController implements ProjectComponentsApi { public ResponseEntity createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { try { Component component = componentsFacade.createProjectComponent(projectId, createComponentRequest); + log.info("Created component {} for project id {} and request {}", component, projectId, createComponentRequest); if (component == null) { log.error("Failed to create component for project '{}'", projectId); return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.error(projectId)); } - return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getName())); + return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.entityCreated(projectId, component.getId())); } catch (Exception e) { log.error("Error while trying to create component for project '" + projectId + "': " + e.getMessage(), e); return componentResponseMapper.toResponseEntity(ComponentsResponseFactory.error(projectId)); @@ -42,6 +43,7 @@ public ResponseEntity createProjectComponent(String pro public ResponseEntity getProjectComponent(String projectId, String componentId) { try { Component component = componentsFacade.getProjectComponent(projectId, componentId); + log.info("Retrieved component '{}' for project '{}': {}", componentId, projectId, component); if (component == null) { return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java index ed85fcd..f36476f 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/facade/ComponentsFacade.java @@ -2,23 +2,41 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.opendevstack.apiservice.project.mock.ComponentMockService; +import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; +import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; +import org.opendevstack.apiservice.externalservice.marketplace.service.MarketplaceService; +import org.opendevstack.apiservice.project.mapper.MarketplaceMapper; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.springframework.stereotype.Service; +import java.util.List; + @Service @AllArgsConstructor @Slf4j public class ComponentsFacade { - private final ComponentMockService marketplaceExternalService; + private final MarketplaceService marketplaceExternalService; + + private final MarketplaceMapper marketplaceMapper; public Component getProjectComponent(String projectId, String componentId) { - return marketplaceExternalService.getProjectComponent(projectId, componentId); + ProjectComponent marketplaceComponent = marketplaceExternalService.getProjectComponent(projectId, componentId); + if (marketplaceComponent == null) { + log.info("Marketplace component with id {} not found", componentId); + return null; + } + return marketplaceMapper.mapMarketplaceComponentToV0Component(marketplaceComponent); } public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { - return marketplaceExternalService.createProjectComponent(projectId, createComponentRequest); + List createComponentParameterList = marketplaceMapper.mapCreateComponentRequestToCreateComponentParameterList(createComponentRequest); + ProjectComponent marketplaceComponent = marketplaceExternalService.createProjectComponent(projectId, createComponentParameterList); + if (marketplaceComponent == null) { + log.error("Failed to create component in marketplace for project with id {}", projectId); + return null; + } + return marketplaceMapper.mapMarketplaceComponentToV0Component(marketplaceComponent); } } diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/MarketplaceMapper.java b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/MarketplaceMapper.java new file mode 100644 index 0000000..f142064 --- /dev/null +++ b/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mapper/MarketplaceMapper.java @@ -0,0 +1,30 @@ +package org.opendevstack.apiservice.project.mapper; + + +import org.mapstruct.Mapper; +import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; +import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; +import org.opendevstack.apiservice.project.model.Component; +import org.opendevstack.apiservice.project.model.CreateComponentRequest; + +import java.util.List; + +@Mapper(componentModel = "spring") +public interface MarketplaceMapper { + + default Component mapMarketplaceComponentToV0Component(ProjectComponent source) { + if (source == null) { + return null; + } + Component target = new Component(); + target.setId(source.getComponentId()); + target.setStatus(source.getStatus()); + return target; + } + + default List mapCreateComponentRequestToCreateComponentParameterList(CreateComponentRequest createComponentRequest) { + return createComponentRequest.getParams().entrySet().stream() + .map(entry -> new CreateComponentParameter(entry.getKey(), "string", entry.getValue())) + .toList(); + } +} diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java index 23aec13..a98c778 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/controller/ProjectComponentsControllerTest.java @@ -40,7 +40,7 @@ void testCreateProjectComponent_whenSuccess_thenReturnOk() throws Exception { Component testComponent = buildTestComponent(); String testProjectId = "testProjectId"; CreateComponentRequest testCreateComponentRequest = buildTestCreateComponentRequest(); - CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(testComponent.getName(), + CreateComponentResponse testServiceResponseSuccess = buildTestCreateComponentResponseSuccess(testComponent.getId(), testProjectId); when(componentsFacade.createProjectComponent(anyString(), any(CreateComponentRequest.class))) diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java similarity index 58% rename from api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java rename to api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java index be94a6f..6397235 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsServiceTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java @@ -3,46 +3,56 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mapstruct.factory.Mappers; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.opendevstack.apiservice.project.mock.ComponentMockService; +import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; +import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; +import org.opendevstack.apiservice.externalservice.marketplace.service.MarketplaceService; +import org.opendevstack.apiservice.project.mapper.MarketplaceMapper; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; -import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestComponent; import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestCreateComponentRequest; +import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestMarketplaceComponent; +import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestMarketplaceCreateComponentParameters; @ExtendWith(MockitoExtension.class) -class ComponentsServiceTest { +class ComponentsFacadeTest { + + private final MarketplaceMapper marketplaceMapper = Mappers.getMapper(MarketplaceMapper.class); @Mock - private ComponentMockService marketPlaceExternalService; + private MarketplaceService marketplaceExternalService; private ComponentsFacade componentsFacade; @BeforeEach void setup() { - componentsFacade = new ComponentsFacade(marketPlaceExternalService); + componentsFacade = new ComponentsFacade(marketplaceExternalService, marketplaceMapper); //TODO } @Test void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { - Component testComponent = buildTestComponent(); + ProjectComponent testComponent = buildTestMarketplaceComponent(); - when(marketPlaceExternalService.getProjectComponent(anyString(), eq("testId"))) + when(marketplaceExternalService.getProjectComponent(anyString(), eq("testId"))) .thenReturn(testComponent); Component retrievedComponent = componentsFacade.getProjectComponent("testId", "testId"); - assertThat(retrievedComponent).isEqualTo(testComponent); + assertThat(retrievedComponent.getId()).isEqualTo(testComponent.getComponentId()); } @Test void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Exception { - when(marketPlaceExternalService.getProjectComponent(anyString(), eq("testId"))) + when(marketplaceExternalService.getProjectComponent(anyString(), eq("testId"))) .thenReturn(null); Component retrievedComponent = componentsFacade.getProjectComponent("testId", "testId"); @@ -51,14 +61,14 @@ void testGetProjectComponent_whenNoComponentFound_thenReturnNull() throws Except @Test void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exception { - Component testComponent = buildTestComponent(); + ProjectComponent testComponent = buildTestMarketplaceComponent(); CreateComponentRequest testRequest = buildTestCreateComponentRequest(); - when(marketPlaceExternalService.createProjectComponent(anyString(), eq(testRequest))) + when(marketplaceExternalService.createProjectComponent(anyString(), any(List.class))) .thenReturn(testComponent); Component retrievedComponent = componentsFacade.createProjectComponent("testId", testRequest); - assertThat(retrievedComponent).isEqualTo(testComponent); + assertThat(retrievedComponent.getId()).isEqualTo(testComponent.getComponentId()); } @@ -66,7 +76,7 @@ void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws void testCreateProjectComponent_whenFailure_thenReturnNull() throws Exception { CreateComponentRequest testRequest = buildTestCreateComponentRequest(); - when(marketPlaceExternalService.createProjectComponent(anyString(), eq(testRequest))) + when(marketplaceExternalService.createProjectComponent(anyString(), any(List.class))) .thenReturn(null); Component retrievedComponent = componentsFacade.createProjectComponent("testId", testRequest); diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestObjectsBuilder.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestObjectsBuilder.java index 60ca92b..14cc84f 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestObjectsBuilder.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/util/TestObjectsBuilder.java @@ -1,10 +1,15 @@ package org.opendevstack.apiservice.project.util; +import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; +import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; import org.opendevstack.apiservice.project.model.Component; import org.opendevstack.apiservice.project.model.CreateComponentRequest; import org.opendevstack.apiservice.project.model.CreateComponentResponse; import org.springframework.http.HttpStatus; +import java.util.ArrayList; +import java.util.List; + public class TestObjectsBuilder { private TestObjectsBuilder() { @@ -19,6 +24,14 @@ public static Component buildTestComponent() { return component; } + public static ProjectComponent buildTestMarketplaceComponent() { + ProjectComponent component = new ProjectComponent(); + component.setComponentId("testComponentId"); + component.setCanBeDeleted(false); + component.setComponentUrl("http://test.component.url"); + return component; + } + public static CreateComponentRequest buildTestCreateComponentRequest() { CreateComponentRequest request = new CreateComponentRequest(); request.setName("testComponentName"); @@ -26,10 +39,17 @@ public static CreateComponentRequest buildTestCreateComponentRequest() { return request; } - public static CreateComponentResponse buildTestCreateComponentResponseSuccess(String componentName, String projectId) { + public static List buildTestMarketplaceCreateComponentParameters() { + List parameters = new ArrayList<>(); + parameters.add(new CreateComponentParameter("name", "string", "testComponentName")); + parameters.add(new CreateComponentParameter("productId", "string", "testProductId")); + return parameters; + } + + public static CreateComponentResponse buildTestCreateComponentResponseSuccess(String componentId, String projectId) { CreateComponentResponse response = new CreateComponentResponse(); response.setErrorCode(HttpStatus.CREATED.value()); - response.setMessage(componentName + " component created successfully in project " + projectId); + response.setMessage(componentId + " component created successfully in project " + projectId); return response; } diff --git a/core/pom.xml b/core/pom.xml index e794fa2..252da50 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -109,6 +109,12 @@ ${project.version} + + org.opendevstack.apiservice + external-service-marketplace + ${project.version} + + org.opendevstack.apiservice api-project-users diff --git a/external-service-marketplace/pom.xml b/external-service-marketplace/pom.xml new file mode 100644 index 0000000..6358551 --- /dev/null +++ b/external-service-marketplace/pom.xml @@ -0,0 +1,129 @@ + + 4.0.0 + + + org.opendevstack.apiservice + devstack-api-service + 0.0.3 + + + external-service-marketplace + External Service Marketplace 2.0 + Service module for integrating with Marketplace 2.0 + + + + + org.opendevstack.apiservice + external-service-api + ${project.version} + + + + + org.springframework.boot + spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.projectlombok + lombok + provided + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.junit.jupiter + junit-jupiter + test + + + + + org.wiremock.integrations + wiremock-spring-boot + 3.10.0 + test + + + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable.version} + + + + + jakarta.annotation + jakarta.annotation-api + + + + + org.springframework.boot + spring-boot-starter-cache + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${project.basedir}/target/generated-sources/openapi/src/main/java + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + diff --git a/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/CreateComponentParameter.java b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/CreateComponentParameter.java new file mode 100644 index 0000000..a4409c3 --- /dev/null +++ b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/CreateComponentParameter.java @@ -0,0 +1,17 @@ +package org.opendevstack.apiservice.externalservice.marketplace.model; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class CreateComponentParameter { + + private String name; + private String type; + private String value; + +} diff --git a/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/ProjectComponent.java b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/ProjectComponent.java new file mode 100644 index 0000000..89b640b --- /dev/null +++ b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model/ProjectComponent.java @@ -0,0 +1,18 @@ +package org.opendevstack.apiservice.externalservice.marketplace.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class ProjectComponent { + + private String componentId; + private String status; + private boolean canBeDeleted; + private String logoUrl; + private String componentUrl; + +} diff --git a/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/MarketplaceService.java b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/MarketplaceService.java new file mode 100644 index 0000000..8873f42 --- /dev/null +++ b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/MarketplaceService.java @@ -0,0 +1,15 @@ +package org.opendevstack.apiservice.externalservice.marketplace.service; + +import org.opendevstack.apiservice.externalservice.api.ExternalService; +import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; +import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; + +import java.util.List; + +public interface MarketplaceService extends ExternalService { + + + ProjectComponent getProjectComponent(String projectId, String componentId); + + ProjectComponent createProjectComponent(String projectId, List params); +} diff --git a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java similarity index 61% rename from api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java rename to external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java index 55ba231..3a984db 100644 --- a/api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/mock/ComponentMockService.java +++ b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java @@ -1,41 +1,41 @@ -package org.opendevstack.apiservice.project.mock; +package org.opendevstack.apiservice.externalservice.marketplace.service.impl; -import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.opendevstack.apiservice.externalservice.api.ExternalService; -import org.opendevstack.apiservice.project.model.Component; -import org.opendevstack.apiservice.project.model.CreateComponentRequest; +import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; +import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; +import org.opendevstack.apiservice.externalservice.marketplace.service.MarketplaceService; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; @Service -@AllArgsConstructor @Slf4j -public class ComponentMockService implements ExternalService { +public class MarketplaceServiceMockImpl implements MarketplaceService { @Override public boolean isHealthy() { return true; } - private Map mockComponentsCache = Collections.synchronizedMap(new HashMap<>()); + private Map mockComponentsCache = Collections.synchronizedMap(new HashMap<>()); - public Component getProjectComponent(String projectId, String componentId) { + public ProjectComponent getProjectComponent(String projectId, String componentId) { log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); ComposedId composedId = new ComposedId(projectId, componentId); return mockComponentsCache.get(composedId); } - public Component createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) { - log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentRequest); - Component mockComponent = new Component(); - mockComponent.setId(generateNextId()); - mockComponent.setName("Mock Component " + mockComponent.getId() + " for project " + projectId); + public ProjectComponent createProjectComponent(String projectId, List createComponentParams) { + log.info("Creating component for project '" + projectId + "'" + " with request: " + createComponentParams); + ProjectComponent mockComponent = new ProjectComponent(); + mockComponent.setComponentId(generateNextId()); + mockComponent.setCanBeDeleted(true); + mockComponent.setStatus("CREATING"); synchronized (mockComponentsCache) { - ComposedId composedId = new ComposedId(projectId, mockComponent.getId()); + ComposedId composedId = new ComposedId(projectId, mockComponent.getComponentId()); mockComponentsCache.put(composedId, mockComponent); } return mockComponent; diff --git a/pom.xml b/pom.xml index 01d9d24..2a5aace 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,7 @@ external-service-ocp external-service-bitbucket external-service-jira + external-service-marketplace external-service-webhookproxy service-projects api-project-users From c90fc230e665b84e778e782a59a284c89636005b Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Tue, 31 Mar 2026 12:24:59 +0200 Subject: [PATCH 3/4] Update test. --- .../apiservice/project/facade/ComponentsFacadeTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java index 6397235..3935839 100644 --- a/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java +++ b/api-project-component-v0/src/test/java/org/opendevstack/apiservice/project/facade/ComponentsFacadeTest.java @@ -6,7 +6,6 @@ import org.mapstruct.factory.Mappers; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.opendevstack.apiservice.externalservice.marketplace.model.CreateComponentParameter; import org.opendevstack.apiservice.externalservice.marketplace.model.ProjectComponent; import org.opendevstack.apiservice.externalservice.marketplace.service.MarketplaceService; import org.opendevstack.apiservice.project.mapper.MarketplaceMapper; @@ -22,7 +21,6 @@ import static org.mockito.Mockito.when; import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestCreateComponentRequest; import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestMarketplaceComponent; -import static org.opendevstack.apiservice.project.util.TestObjectsBuilder.buildTestMarketplaceCreateComponentParameters; @ExtendWith(MockitoExtension.class) class ComponentsFacadeTest { @@ -36,7 +34,7 @@ class ComponentsFacadeTest { @BeforeEach void setup() { - componentsFacade = new ComponentsFacade(marketplaceExternalService, marketplaceMapper); //TODO + componentsFacade = new ComponentsFacade(marketplaceExternalService, marketplaceMapper); } @Test @@ -48,6 +46,7 @@ void testGetProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Exc Component retrievedComponent = componentsFacade.getProjectComponent("testId", "testId"); assertThat(retrievedComponent.getId()).isEqualTo(testComponent.getComponentId()); + assertThat(retrievedComponent.getStatus()).isEqualTo(testComponent.getStatus()); } @Test @@ -69,6 +68,7 @@ void testCreateProjectComponent_whenSuccess_thenReturnCorrectComponent() throws Component retrievedComponent = componentsFacade.createProjectComponent("testId", testRequest); assertThat(retrievedComponent.getId()).isEqualTo(testComponent.getComponentId()); + assertThat(retrievedComponent.getStatus()).isEqualTo(testComponent.getStatus()); } From eba646804e16f96d69cadb84e09168713624266a Mon Sep 17 00:00:00 2001 From: "zxBCN Valeriu_Tuguran,Constantin (IT EDP) EXTERNAL" Date: Tue, 31 Mar 2026 13:26:56 +0200 Subject: [PATCH 4/4] Remove synch from mock. --- .../service/impl/MarketplaceServiceMockImpl.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java index 3a984db..2301a76 100644 --- a/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java +++ b/external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/service/impl/MarketplaceServiceMockImpl.java @@ -20,7 +20,7 @@ public boolean isHealthy() { return true; } - private Map mockComponentsCache = Collections.synchronizedMap(new HashMap<>()); + private Map mockComponentsCache = new HashMap<>(); public ProjectComponent getProjectComponent(String projectId, String componentId) { log.info("Get component with id '" + componentId + "' for project '" + projectId + "'"); @@ -34,10 +34,9 @@ public ProjectComponent createProjectComponent(String projectId, List