Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
636cc1c
Add marketplace api client.
Apr 14, 2026
27682ee
Add marketplace api client.
Apr 14, 2026
2c9e956
Remove unused var.
Apr 14, 2026
6ee3a28
Fix sonarqube complaints.
Apr 14, 2026
cf25bfb
Add delete component functionality - not finished.
Apr 21, 2026
3abe777
Merge branch 'develop' into feature/real-marketplace-components-api-u…
Apr 21, 2026
0e72bc9
Add delete component functionality - not finished.
Apr 21, 2026
4138b18
Implement component existence check and exception handling for duplic…
angelmp01 Apr 22, 2026
911780e
Add API endpoint to retrieve extended information of a project compon…
angelmp01 Apr 27, 2026
3d708a6
Update getComponent to call the new endpoint.
Apr 29, 2026
05fa84f
Implement On-Behalf-Of (OBO) token exchange functionality and enhance…
angelmp01 Apr 29, 2026
db955b7
Fix github comments.
Apr 29, 2026
05a1abf
Refactor exception handling in getProjectComponent to use ComponentNo…
angelmp01 Apr 29, 2026
3a7c372
Add ComponentBadRequestException and enhance exception handling for b…
angelmp01 Apr 29, 2026
2febcc7
Remove unused workflow, odsNamespace, and quickstarterRepository fiel…
angelmp01 Apr 29, 2026
5dff575
Fix test.
Apr 29, 2026
d899671
Merge remote-tracking branch 'origin/feature/real-marketplace-compone…
Apr 29, 2026
f93621f
Add catalog item resolution and enhance component provisioning logic
angelmp01 Apr 30, 2026
fb1f6ab
Merge branch 'feature/real-marketplace-components-api-usage' of githu…
angelmp01 Apr 30, 2026
68b9053
Apply suggestion from @Copilot
angelmp01 Apr 30, 2026
ea8b1d2
Apply suggestions from code review
angelmp01 Apr 30, 2026
512bf76
Enhance encoding and decoding of catalog item IDs and improve excepti…
angelmp01 Apr 30, 2026
89f5e5d
Add unit tests for MarketplaceMapper and enhance MarketplaceServiceIm…
angelmp01 May 5, 2026
ba16253
Add health check endpoints for Catalog and Provisioner in Marketplace…
angelmp01 May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,7 @@ api-project/src/main/java/org/opendevstack/apiservice/project/api
api-project/src/main/java/org/opendevstack/apiservice/project/model
api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/api
api-project-component-v0/src/main/java/org/opendevstack/apiservice/project/model
external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/openapi

**/.openapi-generator

17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,25 @@ check-maven:
clean: check-maven
@echo "$(BLUE)Cleaning build artifacts...$(NC)"
$(MAVEN_WRAPPER) clean
@echo "$(BLUE)Removing all target directories across modules...$(NC)"
@find . -type d -name target -prune -exec rm -rf {} +
@echo "$(BLUE)Removing generated OpenAPI model directories...$(NC)"
@find . -type d -path "*/src/main/java/*/model" \
! -path "./external-service-aap/src/main/java/org/opendevstack/apiservice/externalservice/aap/model" \
! -path "./service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/model" \
! -path "./external-service-projects-info-service/src/main/java/org/opendevstack/apiservice/externalservice/projectsinfoservice/model" \
! -path "./external-service-marketplace/src/main/java/org/opendevstack/apiservice/externalservice/marketplace/model" \
! -path "./external-service-uipath/src/main/java/org/opendevstack/apiservice/externalservice/uipath/model" \
-prune -exec rm -rf {} +
@echo "$(GREEN)✓ Clean complete$(NC)"

## Remove local Maven cache for org.opendevstack.apiservice
clean-cache:
@echo "$(BLUE)Removing local Maven cache for org.opendevstack.apiservice...$(NC)"
@rm -rf "$$HOME/.m2/repository/org/opendevstack/apiservice"
@rm -rf "$$HOME/.m2/repositories/org/opendevstack/apiservice"
@echo "$(GREEN)✓ Maven cache clean complete$(NC)"

## Compile the project
compile: check-java check-maven
@echo "$(BLUE)Compiling project...$(NC)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ paths:
description: Component id
schema:
type: string
format: uuid
responses:
'200':
description: Component information
Expand Down
6 changes: 6 additions & 0 deletions api-project-component-v0/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>core-security</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@ public static CreateComponentResponse forbidden(String path, String message, Com
return buildResponse(HttpStatus.FORBIDDEN, errorKey, path, message);
}

public static CreateComponentResponse conflict(String path, String message, ComponentErrorKey errorKey) {
return buildResponse(HttpStatus.CONFLICT, errorKey, path, message);
}

public static CreateComponentResponse notFound(String path, String message, ComponentErrorKey errorKey) {
return buildResponse(HttpStatus.NOT_FOUND, errorKey, path, message);
}

public static CreateComponentResponse unprocessableEntity(String path, String message, ComponentErrorKey errorKey) {
return buildResponse(HttpStatus.UNPROCESSABLE_ENTITY, errorKey, path, message);
}

public static CreateComponentResponse internalError(String path, String message, ComponentErrorKey errorKey) {
return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR, errorKey, path, message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.opendevstack.apiservice.project.api.ProjectComponentsApi;
import org.opendevstack.apiservice.project.exception.ComponentCreationException;
import org.opendevstack.apiservice.project.exception.ComponentNotFoundException;
import org.opendevstack.apiservice.project.facade.ComponentsFacade;
import org.opendevstack.apiservice.project.mapper.ComponentResponseMapper;
Expand All @@ -15,8 +14,6 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
@AllArgsConstructor
@Slf4j
Expand All @@ -31,20 +28,18 @@ public class ProjectComponentsController implements ProjectComponentsApi {

@Override
public ResponseEntity<CreateComponentResponse> createProjectComponent(String projectId, CreateComponentRequest createComponentRequest) {
Component component = componentsFacade.createProjectComponent(projectId, createComponentRequest);
if (component == null) {
throw new ComponentCreationException(String.format("Failed to create component for project '%s'", projectId));
}
componentsFacade.provisionProjectComponent(projectId, createComponentRequest);

log.info("Created component {} for project id {} and request {}", component, projectId, createComponentRequest);
log.info("Created component '{}' for project '{}'", createComponentRequest.getName(), projectId);
return componentResponseMapper.toResponseEntity(
ComponentsResponseFactory.entityCreated(projectId, component.getId())
ComponentsResponseFactory.entityCreated(projectId, createComponentRequest.getName())
);

}

@Override
public ResponseEntity<Component> getProjectComponent(String projectId, UUID componentId) {
Component component = componentsFacade.getProjectComponent(projectId, componentId.toString());
public ResponseEntity<Component> getProjectComponent(String projectId, String componentId) {
Component component = componentsFacade.getProjectComponent(projectId, componentId);
if (component == null) {
throw new ComponentNotFoundException(
String.format("Component '%s' not found for project '%s'", componentId, projectId)
Expand All @@ -54,4 +49,5 @@ public ResponseEntity<Component> getProjectComponent(String projectId, UUID comp
log.info("Retrieved component '{}' for project '{}': {}", componentId, projectId, component);
return ResponseEntity.status(HttpStatus.OK).body(component);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
import lombok.extern.slf4j.Slf4j;
import org.opendevstack.apiservice.project.controller.ComponentsResponseFactory;
import org.opendevstack.apiservice.project.controller.ProjectComponentsController;
import org.opendevstack.apiservice.project.exception.ComponentAlreadyExistsException;
import org.opendevstack.apiservice.project.exception.ComponentBadRequestException;
import org.opendevstack.apiservice.project.exception.ComponentCreationException;
import org.opendevstack.apiservice.project.exception.ComponentErrorKey;
import org.opendevstack.apiservice.project.exception.ComponentNotFoundException;
import org.opendevstack.apiservice.project.exception.ComponentRetrievalException;
import org.opendevstack.apiservice.project.model.Component;
import org.opendevstack.apiservice.project.model.CreateComponentResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -138,6 +142,54 @@ public ResponseEntity<CreateComponentResponse> handleComponentCreationException(
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}

@ExceptionHandler(ComponentRetrievalException.class)
public ResponseEntity<CreateComponentResponse> handleComponentRetrievalException(
ComponentRetrievalException ex,
HttpServletRequest request) {

log.error("Component retrieval failed: {}", ex.getMessage(), ex);

CreateComponentResponse response = ComponentsResponseFactory.internalError(
request.getRequestURI(),
ex.getMessage(),
ComponentErrorKey.INTERNAL_ERROR
);

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}

@ExceptionHandler(ComponentAlreadyExistsException.class)
public ResponseEntity<CreateComponentResponse> handleComponentAlreadyExistsException(
ComponentAlreadyExistsException ex,
HttpServletRequest request) {

log.warn("Component already exists: {}", ex.getMessage());

CreateComponentResponse response = ComponentsResponseFactory.conflict(
request.getRequestURI(),
ex.getMessage(),
ComponentErrorKey.INVALID_PARAMETERS
);

return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
}

@ExceptionHandler(ComponentBadRequestException.class)
public ResponseEntity<CreateComponentResponse> handleComponentBadRequestException(
ComponentBadRequestException ex,
HttpServletRequest request) {

log.warn("Bad request from downstream service: {}", ex.getMessage());

CreateComponentResponse response = ComponentsResponseFactory.unprocessableEntity(
request.getRequestURI(),
ex.getMessage(),
ComponentErrorKey.INVALID_PARAMETERS
);

return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(response);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<CreateComponentResponse> handleGenericException(
Exception ex,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.opendevstack.apiservice.project.exception;

public class CatalogItemNotFoundException extends RuntimeException {

public CatalogItemNotFoundException(String message) {
super(message);
}

public CatalogItemNotFoundException(String message, Exception e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.opendevstack.apiservice.project.exception;

public class ComponentAlreadyExistsException extends RuntimeException {

public ComponentAlreadyExistsException(String message) {
super(message);
}

public ComponentAlreadyExistsException(String message, Exception e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.opendevstack.apiservice.project.exception;

public class ComponentBadRequestException extends RuntimeException {

public ComponentBadRequestException(String message) {
super(message);
}

public ComponentBadRequestException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ public class ComponentCreationException extends RuntimeException {
public ComponentCreationException(String message) {
super(message);
}

public ComponentCreationException(String message, Exception e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ public class ComponentNotFoundException extends RuntimeException {
public ComponentNotFoundException(String message) {
super(message);
}

public ComponentNotFoundException(String message, Exception e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.opendevstack.apiservice.project.exception;

public class ComponentRetrievalException extends RuntimeException {

public ComponentRetrievalException(String message) {
super(message);
}

public ComponentRetrievalException(String message, Exception e) {
super(message, e);
}
}
Loading
Loading